home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1994 November: Tool Chest / Dev.CD Nov 94.toast / Tool Chest / Development Tools & Languages / • Other Platforms / PCCTS / Documentation / NOTES.newbie < prev    next >
Encoding:
Text File  |  1994-09-14  |  122.7 KB  |  3,183 lines  |  [TEXT/MPS ]

  1. 29 August 94
  2. Version 1.21 of pccts
  3.  
  4. This help file is available via anonymous FTP at:
  5.  
  6.         Node: everest.ee.umn.edu [128.101.144.112]
  7.         File: /pub/pccts/1.22/NOTES.newbie
  8.  
  9. Mirror sites for pccts:
  10.  
  11.      Europe:
  12.  
  13.         Node: ftp.th-darmstadt.de [130.83.55.75]
  14.         Directory: pub/programming/languages/compiler-compiler/pccts
  15.  
  16.                 According to the FAQ this is updated daily.
  17.  
  18.         Node: src.doc.ic.ac.uk
  19.         Directory: /computing/programming/languages/tools/pccts
  20.  
  21.                 Unable to reach this node from my site.
  22.      Also:
  23.  
  24.         Node: ftp.uu.net
  25.         Directory: languages/tools/pccts
  26.  
  27. Mail corrections or additions to moog@polhode.com
  28. ===============================================================================
  29. Miscellaneous
  30. -------------------------------------------------------------------------------
  31. 1.  NEVER choose rule names, #token names, #lexclass names, #errclass
  32. names, etc. which coincide with the reserved words of your C or C++
  33. compiler. Be awake to name collisions with your favorite libraries
  34. and #include files.  One can only imagine the results of definitions like:
  35.  
  36.                 #token FILE "file"
  37.  
  38.                 const: "[0-9]*"
  39.  
  40. 2.  Tokens begin with uppercase characters. Rules begin with lowercase
  41. characters.
  42.  
  43. 3.  When passing the name of the start rule to the ANTLR macro don't
  44. forget to code the trailing function arguments:
  45.  
  46.         /* Not using ASTs  */   ANTLR (grammar(),stdin);
  47.         /* Using ASTs      */   ANTLR (grammar(&ASTroot),stdin);
  48.  
  49.         /* *** Wrong ***   */   ANTLR (grammar,stdin);
  50.  
  51. 4.  When you see a syntax error message that has quotation marks on
  52. separate lines:
  53.  
  54.         line 1: syntax error at "
  55.         " missing ID
  56.  
  57. that probably means that the offending element contains a newline.
  58.  
  59.                                                                      Page 2
  60.  
  61. 5.  Even if your C compiler does not support C++ style comments,
  62. you can use them in the *non-action* portion of the ANTLR source code.
  63. Inside an action (i.e.  <<...>> ) you have to obey the comment
  64. conventions of your compiler.
  65.  
  66. 6.  To place main() in a ".c" file rather than a grammar file (".g")
  67. place:
  68.  
  69.                 #include "stdpccts.h"
  70.  
  71. before invoking the ANTRLR macro. Contributed by N.F. Ross.
  72.  
  73. 7.  ANTLR counts a line which is continued across a newline using
  74. the backslash convention as a single line.  For example:
  75.  
  76.         #header <<
  77.         #define abcd alpha\
  78.                 beta\
  79.                 gamma\
  80.                 delta
  81.         >>
  82.  
  83. This will cause line numbers in ANTLR error messages to be off by 3 compared
  84. to most text editors.
  85.  
  86. 8.  The Purdue Computer Science Department maintains a WWW directory
  87. which includes a pccts page:
  88.  
  89.         URL http://tempest.ecn.purdue.edu:8001/
  90.  
  91.                                                                      Page 3
  92.  
  93. 9.  Suppose one wants to parse files that "include" other files.  The
  94. code in ANTLR (antlr.g) for handling #tokdefs statements demonstrates
  95. how this may be done.
  96.  
  97.     grammar:  ...
  98.  
  99.               | "#tokdefs"  QuotedTerm
  100.  
  101.                 <<{
  102.  
  103.                 zzantlr_state           st;     /* defined in antlr.h  */
  104.                 struct zzdlg_state      dst;    /* defined in dlgdef.h */
  105.                 FILE                    *f;
  106.  
  107.                 UserTokenDefsFile = mystrdup(LATEXT(1));
  108.                 zzsave_antlr_state(&st);
  109.                 zzsave_dlg_state(&dst);
  110.                 f = fopen(StripQuotes(LATEXT(1)),"r");
  111.                 if ( f==NULL ) {
  112.                     warn(eMsg1("cannot open token defs file '%s'",
  113.                                 LATEXT(1)+1));}
  114.                 else {
  115.                     ANTLRm( enum_file(), f, PARSE_ENUM_FILE);
  116.                     UserDefdTokens = 1;
  117.                 }
  118.                 zzrestore_antlr_state(&st);
  119.                 zzrestore_dlg_state(&dst);
  120.                 }>>
  121.  
  122. The code uses zzsave_antlr_state() and zzsave_dlg_state() to save the state
  123. of the current parse.  The ANTLRm macro specifies a starting rule for ANTLR
  124. of "enum_file" and starts DLG in the PARSE_ENUM_FILE state rather than the
  125. default state (which is the current state - whatever it might be).  Because
  126. enum_file() is called without any arguments it appears that enum_file() does
  127. not use ASTs nor pass back any attributes. Contributed by Terence J. Parr.
  128.  
  129. 10.  If an action becomes too large then it will overflow an ANTLR buffer
  130. ("... error: action buffer overflow: size 4000"). If you don't wish to
  131. recompile ANTLR with a larger value for ZZLEXBUFSIZE you can put the
  132. action in an include file and then place a #include in the action
  133. Suggested by David Seidel (dseidel@delphi.com).
  134.  
  135. Splitting an action into two smaller actions will not work if the second
  136. action needs to refer to zzlextext.
  137.  
  138. 11.  When one is using multiple input files (for example "a.g" and "b.g"
  139. to generate "a.c" and "b.c") the only way to place file scope information
  140. in b.c is to place it in #header of the first grammar file.  ANTLR won't
  141. allow file scope information to be copied from b.g into b.c using
  142. "<<...>>" notation.  If one did place a file scope action in the b.g, ANTLR
  143. would try to interpret it as the fail action of the last rule appearing in
  144. a.g. (the first grammar file).  The workaround is to #include b.c in
  145. another file which has your file scope declarations.  You'll probably
  146. need to #include "stdpccts.h" before your file scope definitions.
  147.  
  148. 12.  Multiple parsers can coexist in the same application through use of
  149. the #parser directive (in C output mode).  The #parser statement is not used
  150. with the ANTLR C++ output option because one can simply instantiate a new
  151. parser object.
  152.  
  153.                                                                      Page 4
  154.  
  155. 13.  Don't confuse #[...] with #(...).
  156.  
  157. The first creates a single AST node (usually from a token identifier and
  158. an attribute) using the routine zzmk_ast().  The zzmk_ast() routine must be
  159. supplied by the user (or selected from one of the pccts supplied ones such
  160. as pccts/h/charbuf.h, pccts/h/charptr.*, and pccts/h/int.h).
  161.  
  162. The second creates an AST list (usually more than a single node) from other
  163. ASTs by filling in the "down" field of the first node in the list to create
  164. a root node, and the "sibling" fields of each of remaining ASTs in the
  165. list.  A null pointer is put in the sibling field of the last AST in the
  166. list.  This is performed by the pccts supplied routine zztmake().
  167.  
  168.      #token ID                  "[a-z]*"
  169.      #token COLON               ":"
  170.      #token STMT_WITH_LABEL
  171.  
  172.      id!   : ID <<#0=#[STMT_WITH_LABEL,$1];>>                   /* a1 */
  173.  
  174.                 Creates an AST.  The AST (a single node)
  175.                 contains STMT_WITH_LABEL in the token
  176.                 field - given a traditional version of
  177.                 zzmk_ast().
  178.  
  179.      rule! : id COLON expr                                      /* a2 */
  180.                 <<#0=#(#1,#3);>>
  181.  
  182.                 Creates an AST list with the ID at its
  183.                 root and "expr" as its first (and only) child.
  184.  
  185. The following example (a3) is equivalent to a1, but more confusing because
  186. the two steps above have been combined into a single action statement:
  187.  
  188.      rule! : ID COLON expr
  189.                 <<#0=#(#[STMT_WITH_LABEL,$1],#3);>>             /* a3 */
  190.                                                                      Page 5
  191.  
  192. ===============================================================================
  193. Section on switches and options
  194. -------------------------------------------------------------------------------
  195. 14.  Don't forget about the ANTLR -gd option which provides a trace of
  196. rules which are triggered and exited.
  197.  
  198. The trace option can be useful in sometimes unexpected ways.  For example,
  199. by suitably defining the macros zzTRACEIN and zzTRACEOUT before the
  200. #include of "antlr.h" one can accumulate information on how often each
  201. rule is invoked.
  202.  
  203. 15.  When you want to inspect the code generated by ANTLR you may want to
  204. use the ANTLR -gs switch.  This causes ANTLR to test for a token being
  205. an element of  a lookahead set by using explicit tests with meaningful
  206. token names rather by using the faster bit oriented operations which are
  207. difficult to read.
  208.  
  209. 16.  When using the ANTLR -gk option you probably want to use the DLG -i
  210. option.  As far as I can tell neither option works by itself.
  211. Unfortunately they have different abbreviations so that one can't
  212. use the same symbol for both in a makefile.
  213.  
  214. 17.  When you are debugging code in the rule section and there is no
  215. change to the lexical scanner, you can avoid regeneration of scanner.c
  216. by using the ANTLR -gx option.  However some items from stdpccts.h
  217. can affect the scanner, such as -k -ck and the addition of semantic
  218. predicates - so this optimization should be used with a little care.
  219.  
  220. 18.  One cannot use an interactive scanner (ANTLR -gk option) with the
  221. ANTLR infinite lookahead and backtracking options (syntactic predicates).
  222.  
  223. 19.  If you want backtracking, but not the prefetching of characters and
  224. tokens that one gets with lookahead, then you might want to try using
  225. your own input routine and then using ANTLRs (input supplied by string)
  226. or ANTLRf (input supplied by function) rather than plain ANTLR which
  227. is used in most of the examples.
  228.  
  229. See Example 4 below for an example of an ANTLRf input function.
  230.  
  231. 20.  The format used in #line directive is controlled by the macro
  232.  
  233.                 #define LineInfoFormatStr "# %d \"%s\"\n"
  234.  
  235. which is defined in generic.h.  A change requires recompilation of ANTLR.
  236.  
  237. Prior to version 1.21 ANTLR -gl will sometimes place #line directives in
  238. a column other than column 1.  The temporary workaround is to change
  239. the format string to:
  240.  
  241.                 #define LineInfoFormatStr "\n# %d \"%s\"\n"
  242.  
  243. This is reported as fixed in versions >= 1.21
  244.  
  245. 21.  To make the lexical scanner case insensitive use the DLG -ci
  246. switch.  The analyzer does not change the text, it just ignores case
  247. when matching it against the regular expressions.
  248.  
  249. The problem in version 1.10 with the -ci switch is fixed in versions >= 1.20.
  250.  
  251.                                                                      Page 6
  252.  
  253. 22.  In order to use a different name for the mode.h file it is necessary
  254. to supply the new name using both the ANTLR -fm switch and the DLG -m switch.
  255. ANTLR does not generate mode.h, but it does generate #include statements
  256. which reference it.
  257.  
  258. ===============================================================================
  259. C++ Mode
  260. -------------------------------------------------------------------------------
  261. 23.  When using backtracking (syntactic predicates) ANTLRtoken should be
  262. derived from ANTLRCommonBacktrackingToken rather than ANTLRCommonToken.
  263.                                                                      Page 7
  264.  
  265. ===============================================================================
  266. Section on #token, #tokclass, #tokdef #errclass (but not #lexclass)
  267. -------------------------------------------------------------------------------
  268. 24.  To gobble up everything to a newline use: "~[\n]*".
  269.  
  270. 25.  To match any single character use: "~[]".
  271.  
  272. 26.  The char * array "zztokens" in err.c contains the text for the name of
  273. each token (indexed by the token number).  This can be extremely useful
  274. for debugging and error messages.
  275.  
  276. 27.  If a #token symbol is spelled incorrectly in a rule it will not be
  277. reported by ANTLR unless the ANTLR -w2 option is set.  ANTLR will assign
  278. it a new  #token number which, of course, will never be matched.  Look at
  279. token.h for misspelled terminals or inspect "zztokens[]" in err.c.
  280.  
  281. 28.  If you happen to define the same #token name twice (perhaps
  282. because of inadvertent duplication of a name) you will receive no
  283. error messages from ANTLR or DLG.  ANTLR will simply use the later
  284. definition and forget the earlier one.  Using the ANTLR -w2 option
  285. does not change this behavior.
  286.  
  287. 29.  One cannot continue a regular expression in a #token statement across
  288. lines.  If one tries to use "\" to continue the line the lexical analyzer
  289. will think you are trying to match a newline character.
  290.  
  291. 30.  The escaped literals in #token regular expressions are not identical
  292. to the ANSI escape sequences.  For instance "\v" will yield a match
  293. for "v", not a vertical tab.
  294.  
  295.         \t      \n      \r      \b      - the only escaped letters
  296.  
  297. 31.  In #token regular expressions spaces and tabs which are
  298. not escaped are ignored - thus making it easy to add white space to
  299. a regular expression.
  300.  
  301.         #token  symbol  "[a-z A-Z] [a-z A-Z 0-9]*"
  302.  
  303. 32.  You can achieve a limited form of one character lookahead in the
  304. #token statement action by using zzchar which contains the character following
  305. the regular expression just recognized.
  306.  
  307. 33.  The regular expressions appearing in #errclass declarations must
  308. be unique.
  309.  
  310.                                                                      Page 8
  311.  
  312. 34.  You cannot supply an action (even a null action) for a #token
  313. statement without a regular expression. You'll receive the message:
  314.  
  315.         warning: action cannot be attached to a token name
  316.                 (...token name...); ignored
  317.  
  318. This is a minor problem when the #token is created for use with
  319. attributes or ASTs nodes and has no regular expression:
  320.  
  321.         #token  CAST_EXPR
  322.         #token  SUBSCRIPT_EXPR
  323.         #token  ARGUMENT_LIST
  324.  
  325.         <<
  326.         ... Code related to parsing
  327.         >>
  328.  
  329. ANTLR assumes the code block is the action associated with the #token
  330. immediately preceding it.  It is not obvious what the problem is because
  331. the line number referenced is the END of the code block (">>") rather
  332. than the beginning.  My solution is to follow such #token statements
  333. with a #token which does have a regular expression (or a rule).
  334.  
  335. 35.  Since the lexical analyzer wants to find the longest possible string
  336. that matches a regular expression, it is probably best not to use expressions
  337. like "~[]*" which will gobble up everything to the end-of-file.
  338.  
  339. 36.  The lexical routines zzmode(), zzskip(), and zzmore() do NOT work like
  340. coroutines.  Basically, all they do is set status bits or fields in a
  341. structure owned by the lexical analyzer and then return immediately.  Thus it
  342. is OK to call these routines anywhere from within a lexical action.  You
  343. can even call them from within a subroutine called from a lexical action
  344. routine.
  345.  
  346. See Example 5 below for routines which maintain a stack of modes.
  347.  
  348.                                                                      Page 9
  349.  
  350. 37.  When a string is matched by two #token regular expressions of equal
  351. length, the lexical analyzer will choose the one which appears first in
  352. the source code.  Thus more specific regular expressions should appear
  353. before more general ones:
  354.  
  355.         #token  HELP    "help"         /*  should appear before "symbol" */
  356.         #token  symbol  "[a-zA-Z]*"    /*  should appear after keywords  */
  357.  
  358. Some of these may be caught by using the DLG switch -Wambiguity.
  359. Consider the following grammar:
  360.  
  361.         #header <<
  362.         #include "charbuf.h"
  363.         >>
  364.         <<
  365.         int main() {
  366.                 ANTLR (statement(),stdin);
  367.                 return 0;
  368.         }
  369.         >>
  370.  
  371.         #token  WhiteSpace      "[\ \t]"        <<zzskip();>>
  372.         #token  ID              "[a-z A-Z]*"
  373.         #token  HELP            "HELP"
  374.  
  375.         statement
  376.                 : HELP "@"      <<printf("token HELP\n");>>    /* a1 */
  377.                 | "inline" "@"  <<printf("token inline\n");>>  /* a2 */
  378.                 | ID "@"        <<printf("token ID\n");>>      /* a3 */
  379.                 ;
  380.  
  381. Is an in-line regular expression treated any differently than a regular
  382. expression appearing in a #token statement ?  No! ANTLR/DLG does *NOT*
  383. check for a match to "inline" (line a2)  before attempting a match to the
  384. regular expressions defined by #token statements. The first two
  385. alternatives ("a1" and "a2") will NEVER be matched. All of this will be
  386. clear from examination of the file "parser.dlg".
  387.  
  388. If one builds this example using the DLG switch -Wambiguity one gets
  389. the message:
  390.  
  391.         dlg warning: ambigious regular expression  3  4
  392.         dlg warning: ambigious regular expression  3  5
  393.  
  394. The numbers which appear in the DLG message refer to the assigned token
  395. numbers.  Examine the array zztokens[] in err.c to find the regular
  396. expression which corresponds to the token number reported by DLG.
  397.  
  398.         ANTLRChar *zztokens[6]={
  399.                 /* 00 */        "Invalid",
  400.                 /* 01 */        "@",
  401.                 /* 02 */        "WhiteSpace",
  402.                 /* 03 */        "ID",
  403.                 /* 04 */        "HELP",
  404.                 /* 05 */        "inline"
  405.         };
  406.  
  407. One can also look at the file "scan.c" in which action 4 would
  408. appear in the function "static void act4() {...}".
  409.  
  410. The best advice is to follow the example of the Master, TJP, and place
  411. things like #token ID at the end of the grammar file.
  412.  
  413.                                                                      Page 10
  414.  
  415. 38.  The DLG lexical analyzer is not able to backtrack.  Consider the
  416. following example:
  417.  
  418.         #token          "[\ \t]*]       <<zzskip();>>
  419.         #token ELSE     "else"
  420.         #token ELSEIF   "else [\ \t]* if"
  421.         #token STOP     "stop"
  422.  
  423. with input:
  424.  
  425.         else stop
  426.  
  427. When DLG gets to the end of "else" it realizes that the spaces will allow
  428. it to match a longer string than "else" by itself. So DLG starts to accept
  429. the spaces. When DLG gets to the initial "s" in "stop" it realizes it has
  430. gone too far - but it can't backtrack.  It passes back an error status to
  431. ANTLR which (normally) prints out something like:
  432.  
  433.                 invalid token near line 1 (text was 'else ') ...
  434.  
  435. There is an "extra" space between the "else" and the closing single quote
  436. mark.
  437.  
  438. The fix for this particular example was to make ELSE accept the trailing
  439. spaces.
  440.  
  441.         #token          "[\ \t]*]       <<zzskip();>>
  442.         #token ELSE     "else [\ \t]*"
  443.         #token ELSEIF   "else [\ \t]* if"
  444.  
  445. In other cases you may want to use #lexclass.  You'll need to eliminate
  446. trailing space in the action part of the #token statement or have an
  447. attribute processing routine that can tolerate trailing spaces.  In many
  448. cases the actual text of the reserved words is unimportant since only the
  449. token number is used.
  450.  
  451. This problem is not detected by the DLG option -Wambiguity.
  452.  
  453. 39.  In converting a long list of tokens appearing in a rule to use #tokclass
  454. I simply replaced the rule, in situ, with the #tokclass directive and did a
  455. global replace of the rule name with a new name in which the first letter
  456. was capitalized.  It took me a while to realize that the ANTLR message:
  457.  
  458.         xxx.g, line 123: warning: redefinition of tokclass or conflict
  459.                  w/token 'Literal'; ignored
  460.  
  461. meant that I had used the #tokclass "Literal" before it was defined.
  462. Only rules, not tokens, can be used in forward references.  The problem
  463. was fixed by moving the #tokclass statement up to the #token section of
  464. the file.
  465.  
  466. 40.  The char * variable zzbegexpr and zzendexpr point to the start and end
  467. of the string last matched by a regular expression in a #token statement.
  468.  
  469. However, the char array pointed to by zzlextext may be larger than the
  470. string pointed to by zzbegexpr and zzendexpr because it includes substrings
  471. accumulated through the use of zzmore().
  472.  
  473.                                                                      Page 11
  474.  
  475. 41.  The preprocessor symbol ZZCOL in the lexical scanner controls the
  476. update of column information. This doesn't cause the zzsyn() routine to
  477. report the position of tokens causing the error.  You'll still have to
  478. write that yourself.  The problem, I think, is that, due to look-ahead,
  479. the value of zzendcol will not be synchronized with the token causing the
  480. error, so that the problem becomes non-trivial.
  481.  
  482. 42.  If you want to use ZZCOL to keep track of the column position
  483. remember to adjust zzendcol in the lexical action when a character is not
  484. one print position wide (e.g. tabs or non-printing characters).
  485.  
  486. 43.  In version 1.00 it was common to change the token code based on
  487. semantic routines in the #token actions.  With the addition of semantic
  488. predicates in 1.06 this technique is now frowned upon.
  489.  
  490. Old style:
  491.  
  492.         #token TypedefName
  493.         #token ID  "[a-z A-Z]*"
  494.                 <<{if (isTypedefName(LATEXT(1))) NLA=TypedefName;};>>
  495.  
  496. New Style:
  497.  
  498.         #token ID  "[a-z A-Z]*"
  499.  
  500.         typedefName : <<LA(1)==ID ? isTypedefName(LATEXT(1)) : 1>> ID;
  501.  
  502. See the section on semantic predicates for a longer explanation.
  503.  
  504.                                                                      Page 12
  505.  
  506. 44.  DLG has no operator like grep's "^" which anchors a pattern to the
  507. beginning of a line.  One can use tests based on zzbegcol only if column
  508. information is selected (#define ZZCOL) AND one is NOT using infinite
  509. lookahead mode (syntactic predicates).  A technique which does not depend
  510. on zzbegcol is to look for the newline character and then enter a special
  511. #lexclass.
  512.  
  513. Consider the problem of recognizing lines which have a "!" as the first
  514. character of a line.  A possible solution suggested by Doug Cuthbertson
  515. is:
  516.  
  517.     #token "\n"          <<zzline++; zzmode(BEGIN_LINE);>>
  518.  
  519. *** or ***
  520.  
  521.     #token "\n"          <<zzline++;
  522.                            if (zzchar=='!') zzmode(BEGIN_LINE);>>
  523.  
  524.     #lexclass BEGIN_LINE
  525.     #token BANG "!"      <<zzmode(START);>>
  526.     #token      "~[]"    <<zzmode(START); zzmore();>>
  527.  
  528. When a newline is encountered the #lexclass BEGIN_LINE is entered.  If
  529. the next character is a "!" it returns the token "BANG" and returns
  530. to #lexclass START.  If the next character is anything else it calls
  531. zzmore to accumulate additional characters for the token and, as before,
  532. returns to #lexclass START.  (The order of calls to zzmode() and zzmore()
  533. is not significant).
  534.  
  535. There are two limitations to this.
  536.  
  537. a. If there are other single character tokens which can appear in the first
  538. column then using zzmore() won't be sufficient to work around the problem
  539. because the entire (one character) token has already been consumed.  Thus
  540. all single character tokens which can appear in column 1 must appear in
  541. both #lexclass START and #lexclass BEGIN_LINE.
  542.  
  543. b. The first character of the first line is not preceded by a newline.
  544. thus DLG will be starting in the wrong state.  Thus you might want to rename
  545. "BEGIN_LINE" to "START" and "START" to "NORMAL".
  546.  
  547. Another solution is to use ANTLRf (input from a function) to insert
  548. your own function to do the kind of lexical processing which is difficult
  549. to express in DLG.
  550.  
  551. In 1.20 the macro ANTLRm was added.  it is similar to ANTLR, but has an
  552. extra argument which allows one to specify the lexical class which is
  553. passed to zzmode() to specify the initial #lexclass state of DLG.
  554.  
  555. 45.  In version 1.10 there were problems using 8 bit characters with DLG.
  556. Versions >= 1.20 of ANTLR/DLG work with 8 bit character sets when they are
  557. compiled in a mode in which char variables are by default unsigned (the
  558. g++ option "-funsigned-char"). This should be combined with  a call to
  559. setlocale (LC_ALL,"") to replace the default locale of "C" with the user's
  560. native locale.  This is system dependent - it works with Unix systems but
  561. not DOS.  Contributed by Ulfar Erlingsson (ulfarerl@rhi.hi.is).
  562.  
  563. See Example 4 below.
  564.                                                                      Page 13
  565.  
  566. ===============================================================================
  567. Section on #lexclass
  568. -------------------------------------------------------------------------------
  569. 46.  Special care should be taken when using "in-line" regular expressions
  570. in rules if there are multiple lexical classes #lexclass).  ANTLR will
  571. place such regular expressions in the last lexical class defined.  If
  572. the last lexical class was not START you may be surprised.
  573.  
  574.         #lexclass START
  575.         ....
  576.         #lexclass COMMENT
  577.         ....
  578.  
  579.         inline_example: symbol "=" expression
  580.  
  581.                 This will place "=" in the #lexclass COMMENT (where
  582.                 it will never be matched) rather than the START #lexclass
  583.                 where the user meant it to be.
  584.  
  585. Since it is okay to specify parts of the #lexclass in several pieces
  586. it might be a good idea when using #lexclass to place "#lexclass START"
  587. just before the first rule - then any in-line definitions of tokens
  588. will be placed in the START #lexclass automatically.
  589.  
  590.         #lexclass START
  591.         ...
  592.         #lexclass A
  593.         ...
  594.         #lexclass B
  595.         ...
  596.         #lexclass START
  597.  
  598. 47.  A good example of the use of #lexclass are the definitions for C
  599. and C++ style comments, character literals, and string literals which
  600. can be found in pccts/lang/C/decl.g - or see Example 1 below.
  601.  
  602. 48.  The initial #lexclass of DLG is set by a data statement to START
  603. (which is 0).  Unlike ANTLRm, the traditional ANTLR macros (ANTLRf, ANTLRs,
  604. and ANTLR) do NOT reset the #lexclass. If you call ANTLR multiple times
  605. during a program (for instance to parse each statement of a line-oriented
  606. language independently) DLG will resume in the #lexclass that it was in
  607. when ANTLR returned.  If you want to restart DLG in the START state you
  608. should precede the call to ANTLR with
  609.  
  610.                 zzmode(START);
  611. or use:
  612.                 ANTLRm (myStartRule(),myStartMode);
  613.  
  614.                                                                      Page 14
  615.  
  616. 49.  Consider the problem of a grammar in which a statement is composed
  617. of clauses, each of which has its own #lexclass and in which a given
  618. word is "reserved" in some clauses and not others:
  619.  
  620.         #1;1-JAN-94 01:23:34;enable;a b c d;this is a comment;
  621.         #2;1-JAN-94 08:01:56;operator;smith;move to another station;
  622.         #3;1-JAN-94 09:10:11;move;old pos=5.0 new pos=6.0;operator request;
  623.         #4;1-JAN-94 10:11:12;set-alarm;beeper;2-JAN-94 00:00:01;
  624.  
  625. One would like to reuse a #lexclass if possible. There is no problem with
  626. maintaining a stack of modes (#lexclass numbers) and pushing a new mode
  627. onto the stack each time a new #lexclass subroutine is called.  How to do
  628. this is demonstrated in Example 5.  The problem appears when it is
  629. necessary to leave a #lexclass and return more than one level.  To be more
  630. specific, a #token action can only be executed when one or more characters
  631. is consumed - so to return through three levels of #lexclass calls would
  632. appear to require the consumption of at least three characters.  In the
  633. case of balanced constructs like "...", and '...', or (...) this is not a
  634. problem since the terminating character can be used to trigger the #token
  635. action. However, if the scan is terminated by a "separator", such as the
  636. semi-colon above (";"), one cannot use the same technique.  Once the
  637. semi-colon is consumed it is unavailable for the other #lexclass routines
  638. on the stack to see.
  639.  
  640. My solution is to allow the user to specify (during the call to pushMode)
  641. a "lookahead" routine to be called when the corresponding element of the
  642. mode stack is popped.  At that point the "lookahead" routine can examine
  643. zzchar to determine whether it also wants to pop the stack, and so on up
  644. the mode stack.  The consumption of a single character can result in
  645. popping multiple modes from the mode stack based on a single character of
  646. lookahead.  See the second part of Example 5 below.
  647.  
  648. Continuing with the example of the log file (above): each statement type
  649. has its fields in a specific order.  When the statement type is recognized
  650. a pointer is set to a list of the #lexclasses which is in the same order as
  651. the remaining fields of that kind of statement.  An action attached to
  652. every #token which recognizes a semi-colon (";") advances a pointer in
  653. the list of #lexclasses and then changes the #lexclass by calling zzmode()
  654. to set the #lexclass for the next field of the statement.
  655.                                                                      Page 15
  656.  
  657. ===============================================================================
  658. Section on rules
  659. -------------------------------------------------------------------------------
  660. 50.  If a rule is not used (is an orphan) it can lead to unanticipated
  661. reports of ambiguity.  Use the ANTLR cross-reference option (-cr) to
  662. locate rules which are not referenced.  Not verified in version 1.20.
  663.  
  664. 51.  ANTLR attempts to deduce "start" rules by looking for rules which
  665. are not referenced by any other rules.  When it finds such a rule it
  666. assumes that an EOF token ("@") should be there and adds one if the
  667. user did not code one.  This is the only case, according to TJP, when
  668. ANTLR adds something to the user's grammar.
  669.  
  670. 52.  To express the idea "any single token is acceptable at this point"
  671. use the "." token wild-card.  This can be very useful for providing a
  672. context dependent error message, rather than the all purpose message
  673. "syntax error".
  674.  
  675.         if-stmt : IF "\(" expr "\)" stmt
  676.                 | IF .   <<printf("If statement requires expression ",
  677.                                         "enclosed in parenthesis");
  678.                            PARSE_FAIL;
  679.                          >>
  680.  
  681. It is probably best not to use expressions such as:
  682.  
  683.         ignore:  (.)*           /* Not a good idea */
  684.  
  685. which will gobble up everything to the end-of-file.
  686.  
  687. 53.  New to version 1.20 is the "~" operator for tokens.  It allows
  688. one to specify tokens which must NOT match in order to match a rule.
  689.  
  690. The "~" operator cannot be applied to rules.  To express the idea
  691. "if this rule doesn't match try to match this other rule" use
  692. syntactic predicates.
  693.  
  694. 54.  Some constructs which are bound to cause warnings about
  695. ambiguities:
  696.  
  697.         rule : a { ( b | c )* };
  698.  
  699.         rule : a { b };
  700.            b : ( c )*;
  701.  
  702.         rule : a c*;
  703.            a : b { c };
  704.  
  705.         rule : a { b | c | };
  706.  
  707.                                                                      Page 16
  708.  
  709. 55.  Don't confuse init-actions with actions which precede a rule. If the
  710. first element following the start of a rule or sub-rule is an action it is
  711. always interpreted as an init-action.
  712.  
  713. An init-action occurs in a scope which include the entire rule or sub-rule.
  714. An action which is NOT an init-action is enclosed in "{" and "}" during
  715. generation of code for the rule and has essentially zero scope - the
  716. action itself.
  717.  
  718. The difference between an init-action and an action which precedes a rule
  719. can be especially confusing when an action appears at the start of an
  720. alternative:
  721.  
  722. These APPEAR to be almost identical, but they aren't:
  723.  
  724.       b  : <<int i=0;>>  b1 > [i]  /* b1  <<...>> is an init-action        */
  725.          | <<int j=0;>>  b2 > [j]  /* b2  <<...>> is part of the rule      */
  726.          ;                         /*  and will cause a compilation error  */
  727.  
  728. On line "b1" the <<...>> appears immediately after the beginning of the
  729. rule making it an init-action.  On line "b2" the <<...>> does NOT appear at
  730. the start of a rule or sub-rule, thus it is interpreted as an action which
  731. happens to precede the rule.
  732.  
  733. This can be especially dangerous if you are in the habit of rearranging
  734. the order of alternatives in a rule.  For instance:
  735.  
  736. Changing this:
  737.  
  738.       b  : <<int i=0,j=0;>> <<i++;>>  b1 > [i]       /* c1 */
  739.          | <<j++;>>  b1 > [i]                        /* c2 */
  740.          ;
  741.  
  742. to:
  743.  
  744.       b  : /* empty production */                    /* d1 */
  745.          | <<int i=0,j=0;>> <<i++;>>  b1 > [i]       /* d2 */
  746.          | <<j++;>>  b1 > [i]
  747.          ;
  748.  
  749. or to this:
  750.  
  751.       b
  752.          : <<j++;>>  b1 > [i]                        /* e1 */
  753.          | <<int i=0,j=0;>> <<i++;>>  b1 > [i]       /* e2 */
  754.  
  755. changes an init-action into a non-init action, and vice-versa.
  756.  
  757.                                                                      Page 17
  758.  
  759. 56.  A particularly nasty form of the init-action problem is when
  760. an empty sub-rule has an associated action:
  761.  
  762.         rule!: ID (
  763.                     /* empty */
  764.                         <<#0=#[ID,$1.1];>>
  765.                   | array_bounds
  766.                         <<#0=#[T_array_declaration,$1.1],#1);>>
  767.                   )
  768.              ;
  769.  
  770. Since there is no reserved word in pccts for epsilon, the action
  771. for the empty arm of the sub-rule becomes the init-action.  For
  772. this reason it's wise to follow one of the following conventions
  773. (1) represent epsilon with an empty rule "()" or (2) put empty
  774. as the last rule in a list of alternatives:
  775.  
  776.         rule!: ID (
  777.                     ()  <<#0=#[ID,$1.1];>>
  778.                   | array_bounds
  779.                         <<#0=#[T_array_declaration,$1.1],#1);>>
  780.                   )
  781.              ;
  782.  
  783. The cost of using "()" to represent epsilon is the execution of the macro
  784. zzBLOCK() at the start of the sub-rule and zzEXIT() at the end of the
  785. sub-rule. Macro zzBLOCK() creates a temporary stack pointer for the
  786. attribute stack and checks for overflow.  Macro zzEXIT() pops any
  787. attributes that might have been placed on attribute stack.  Since no
  788. attribute stack operations take place for epsilon this is wasted CPU
  789. cycles, however this is probably not a significant cost for many users.
  790.  
  791. 57.  Another form of problem caused by init-action occurs when one
  792. comments out a rule in the grammar in order to test an idea:
  793.  
  794.         rule                          /* a1 */
  795.                 : <<init-action;>     /* a2 */
  796.         ////      rule_a              /* a3 */
  797.                 | rule_b              /* a4 */
  798.                 | rule_c              /* a5 */
  799.  
  800. In this case one only wanted to comment out the "rule_a" reference
  801. in line "a3".  The reference is indeed gone, but the change has
  802. introduced an epsilon production - which probably creates a large
  803. number of ambiguities.  Without the init-action the ":" would have
  804. probably have been commented out also, and ANTLR would report a
  805. syntax error - thus preventing one from shooting oneself in the foot.
  806.  
  807. 58.   In the case of sub-rules such as (...)+, (...)*, and {...} the
  808. init-action is executed just once before the sub-rule is entered.
  809. Consider the following example from section 3.6.1 (page 29) of the 1.00
  810. manual:
  811.  
  812.         a : <<List *p=NULL;>>                   // initialize list
  813.             Type
  814.             (  <<int i=0;>>                     // initialize index
  815.                Var <<append(p,i++,$1);>>
  816.             )*
  817.             <<OperateOn(p);>>
  818.           ;
  819.  
  820.                                                                      Page 18
  821.  
  822. 59.  Associativity and precedence of operations is determined by
  823. nesting of rules.  In the example below "=" associates to the right
  824. and has the lowest precedence.  Operators "+" and "*" associate to
  825. the left with "*" having the highest precedence.
  826.  
  827.         expr0   : expr1 {"=" expr0};
  828.         expr1   : expr2 ("\+" expr2)*;
  829.         expr2   : expr3 ("\*" expr3)*;
  830.         expr3   : ID;
  831.  
  832. See Example 2.
  833.  
  834. 60.  Fail actions for a rule can be placed after the final ";" of
  835. a rule.  These will be:
  836.  
  837.          "executed after a syntax error is detected but before
  838.           a message is printed and the attributes have been destroyed.
  839.           However, attributes are not valid here because one does not
  840.           know at what point the error occurred and which attributes
  841.           even exist.  Fail actions are often useful for cleaning up
  842.           data structures or freeing memory."
  843.  
  844.                                                 (Page 29 of 1.00 manual)
  845.  
  846.       Example of a fail action:
  847.  
  848.           a : <<List *p=NULL;>>
  849.               ( Var <<append(p,$1);>> )+
  850.                   <<operateOn(p);rmlist(p);>>
  851.             ; <<rmlist(p);>>
  852.               **************  <--- Fail Action
  853.  
  854. 61.  When you have rules with large amounts of lookahead (that may
  855. cross several lines) you can use the ANTLR -gk option to make an
  856. ANTLR-generated parser delay lookahead fetches until absolutely
  857. necessary. To get better line number information (e.g. for error
  858. messages or #line directives) place an action which will save
  859. "zzline" in a variable at the start of the production where you
  860. want better line number information:
  861.  
  862.     a : <<int saveCurrentLine;>>
  863.         <<saveCurrentLine = zzline;>>   A B C
  864.                  << /* use saveCurrentLine not zzline here */ >>
  865.       | <<saveCurrentLine = zzline;>>   A B D
  866.                  << /* use saveCurrentLine not zzline here */ >>
  867.       ;
  868.  
  869. After the production has been matched you can use saveCurrentLine
  870. rather than the bogus "zzline".
  871.  
  872. Contributed by Terence "The ANTLR Guy" Parr (parrt@acm.org)
  873.  
  874. In version 1.20 a new macro, ZZINF_LINE(), was added to extract line
  875. information in a manner similar to LATEXT when using infinite lookahead
  876. mode.  See the page 6 of the 1.20 release notes for more information.
  877. There is nothing like ZZINF_COL() for column information, but it should
  878. be easy to create using ZZINF_LINE() as a model.
  879.  
  880. 62.  An easy way to get a list of the names of all the rules is
  881. to grep tokens.h for the string "void" or edit the output from ANTLR
  882. run with the  -cr option (cross-reference).
  883.  
  884.                                                                      Page 19
  885.  
  886. 63.  It took me a while to understand in an intuitive way the difference
  887. between full LL(k) lookahead given by the ANTLR -k switch and the
  888. linear approximation given by the ANTLR -ck switch.  This was in spite
  889. of the example given in section 5 (pages 18 to 21) of the 1.10 release notes.
  890.  
  891. Most of the time I run ANTLR with -k 1 and -ck 2.  Because I didn't
  892. understand the linear approximation I didn't understand the warnings about
  893. ambiguity.  I couldn't understand why ANLTR would complain about something
  894. which I thought was obviously parse-able with the lookahead available.
  895. Was it a bug or was it me ? I would try to make the messages go away
  896. totally, which was sometimes very hard.  If I had understood the linear
  897. approximation I might have been able to fix them easily or at least have
  898. realized that there was no problem with the grammar, just with the
  899. limitations of the linear approximation.
  900.  
  901. I will restrict the discussion to the case of "-k 1" and "-ck 2".
  902.  
  903. Consider the following example:
  904.  
  905.         rule1   : rule2a | rule2b | rule2c ;
  906.         rule2a  : A X | B Y | C Z ;
  907.         rule2b  : B X | B Z ;
  908.         rule2c  : C X ;
  909.  
  910. It should be clear that with the sentence being only two tokens this
  911. should be parseable with LL(2).
  912.  
  913. Instead, because k=1 and ck=2 ANTLR will produce the following messages:
  914.  
  915.         /pccts120/bin/antlr -k 1 -gs -ck 2 -gh example.g
  916.         Antlr parser generator   Version 1.20   1989-1994
  917.         example.g, line 23: warning: alts 1 and 2 of the rule itself
  918.                  ambiguous upon { B }, { X Z }
  919.         example.g, line 23: warning: alts 1 and 3 of the rule itself
  920.                  ambiguous upon { C }, { X }
  921.  
  922. The code generated resembles the following:
  923.  
  924.         if      (LA(1)==A || LA(1)==B || LA(1)==C) &&
  925.                 (LA(2)==X || LA(2)==Y || LA(2)==Z) then rule2a()
  926.  
  927.         else if (LA(1)==B) &&
  928.                 (LA(2)==X || LA(2)==Y) then rule2b()
  929.  
  930.         else if (LA(1)==C) &&
  931.                 (LA(2)==Z) then rule3a()
  932.         ...
  933.  
  934. This might be called "product-of-sums".  There is an "or" part for
  935. LA(1), an "or" part for LA(2), and they are combined using "and".
  936. To match, the first lookahead token must be in the first set and the second
  937. lookahead token must be in the second set.  It doesn't matter that what
  938. one really wants is:
  939.                                                                      Page 20
  940.  
  941.         if      (LA(1)==A && LA(2)==X) ||
  942.                 (LA(1)==B && LA(2)==Y) ||
  943.                 (LA(1)==C && LA(2)==Z) then rule2a()
  944.  
  945.         else if (LA(1)==B && LA(2)==X) ||
  946.                 (LA(1)==B && LA(2)==Z) then rule2b()
  947.  
  948.         else if (LA(1)==C && LA(2)==X) then rule2c()
  949.  
  950. This happens to be "product-of-sums" but the real problem is that each
  951. product involves one element from LA(1) and one from LA(2) and as the
  952. number of possible tokens increases the number of terms grows as N**2.
  953. With the linear approximation the number of terms grows (surprise)
  954. linearly in the number of tokens.
  955.  
  956. ANTLR won't do this with k=1, it will only do "product-of-sums". However,
  957. all is not lost - you simply add a few well chosen semantic predicates
  958. which you have computed using your LL(k>1), all purpose, carbon based,
  959. analog computer.
  960.  
  961. The linear approximation selects for each branch of the "if" a set which
  962. MAY include more than what is wanted. It never selects a subset of the
  963. correct lookahead sets!  We simply insert a hand-coded version of the
  964. LL(2) computation.  It's ugly, especially in this case, but it fixes the
  965. problem.  In large grammars it may not be possible to run ANTLR with k=2,
  966. so this fixes a few rules which cause problems.  The generated parser may
  967. run faster because it will have to evaluate fewer terms at execution time.
  968.  
  969.         <<
  970.         int bypass_rule2a() {
  971.           if ( LA(1)==B && LA(2)==Y ) return 0;
  972.           if ( LA(1)==B ) return 1;
  973.           if ( LA(1)==C && LA(2)==X ) return 1;
  974.           return 0;
  975.         }
  976.         >>
  977.  
  978.         rule1   :
  979.                 <<bypass_rule2a()>>? rule2a | rule2b | rule2c ;
  980.         rule2a  : A X | B Y | C Z ;
  981.         rule2b  : B X | B Z ;
  982.         rule2c  : C X ;
  983.  
  984. The real cases I've coded  have shorter code sequences in the semantic
  985. predicate.  I coded this as a function to make it easier to read and
  986. because there is a bug in 1.1x and 1.2x which prevents semantic predicates
  987. from crossing lines.  Another reason to use a function (or macro) is to
  988. make it easier to read the generated code to determine when your semantic
  989. predicate is being hoisted too high (it's easy to find references to a
  990. function name with the editor - but difficult to locate a particular
  991. sequence of "LA(1)" and "LA(2)" tests.  Predicate hoisting is a separate
  992. issue which is described elsewhere in this note.
  993.                                                                      Page 21
  994.  
  995. In some cases of reported ambiguity it is not necessary to add semantic
  996. predicates because no VALID token sequence could get to the wrong rule.
  997. If the token sequence were invalid it would be detected by the grammar
  998. eventually, although perhaps not where one might wish.  In other cases
  999. the only necessary action is a reordering of the ambiguous rules so
  1000. that a more specific rule is tested first.  The error messages still
  1001. appear, but one can ignore them or place a trivial semantic predicate
  1002. (i.e. <<1>>? ) in front of the later rules.  This makes ANTLR happy
  1003. because it thinks you've added a semantic predicate which fixes things.
  1004.  
  1005. Some constructs just invite problems.  For instance in C++ with a suitable
  1006. definition of the class "C" one can write:
  1007.  
  1008.                 C a,b,c                         /* a1 */
  1009.                 a.func1(b);                     /* a2 */
  1010.                 a.func2()=c;                    /* a3 */
  1011.                 a = b;                          /* a4 */
  1012.                 a.operator =(b);                /* a5 */
  1013.  
  1014. Statement a5 happens to place an "=" (or any of the usual C++ operators)
  1015. in a token position where it can cause a lot of ambiguity in the lookahead.
  1016. set.  I eventually solved this particular problem by creating a special
  1017. #lexclass for things which follow "operator".  I use an entirely different
  1018. token number for such operators - thereby avoiding the whole problem.
  1019.  
  1020.         //
  1021.         //  C++ operator sequences
  1022.         //
  1023.         //  operator <type_name>
  1024.         //  operator <special characters>
  1025.         //
  1026.         //  There must be at least one non-alphanumeric character between
  1027.         //  "operator" and operator name - otherwise they would be run
  1028.         //  together - ("operatorint" instead of "operator int")
  1029.         //
  1030.  
  1031.         #lexclass LEX_OPERATOR
  1032.         #token  FILLER_C1               "[\ \t]*"
  1033.                   <<zzskip();
  1034.                    if( isalnum(zzchar) ) zzmode(START);
  1035.                   >>
  1036.         #token  OPERATOR_STRING         "[\+\-\*\/\%\^\&\|\~\!\=\<\>]*"
  1037.                                 <<zzmode(START);>>
  1038.         #token  FILLER_C2               "\(\) | \[\] "
  1039.                                 <<NLA=OPERATOR_STRING;zzmode(START);>>
  1040.                                                                      Page 22
  1041.  
  1042. ===============================================================================
  1043. Section on Attributes
  1044. -------------------------------------------------------------------------------
  1045. 64.  Attributes are built automatically only for terminals.  For
  1046. rules (non-terminals) one must assign an attribute to $0, use the
  1047. $[token,...] convention for creating attributes, or use zzcr_attr().
  1048.  
  1049. 65.  The way to access the text (or whatever) part of an attribute
  1050. depends on the way the attribute is stored.
  1051.  
  1052. If one uses the pccts supplied routine "pccts/h/charbuf.h" then
  1053.  
  1054.         id : "[a-z]+"           <<printf("Token is %s\n",$1.text);>>
  1055.  
  1056. If one uses the pccts supplied routine "pccts/h/charptr.c" and
  1057. "pccts/h/charptr.h" then:
  1058.  
  1059.         id : "[a-z]+"           <<printf("Token is %s\n",$1);>>
  1060.  
  1061. If one uses the pccts supplied routine "pccts/h/int.h" (which
  1062. stores numbers only) then:
  1063.  
  1064.         number : "[0-9]+"       <<printf ("Token is %d\n",$1);>>
  1065.  
  1066.                 Note the use of %d rather than %s in the printf() format.
  1067.  
  1068. 66.  The expression $$ refers to the attribute of the named rule.
  1069. The expression $0 refers to the attribute of the the enclosing rule,
  1070. (which might be a sub-rule).
  1071.  
  1072.         rule : a b (c d (e f g) h) i
  1073.  
  1074. For (e f g) $0 becomes $3 of (c d  ... h).  For (c d ... h) $0 becomes
  1075. $3 of (a b ... i).  However $$ always is equivalent to $rule.
  1076.  
  1077. 67.  If you define a zzcr_attr() or zzmk_attr() which allocates resources
  1078. such as strings from the heap don't forget to define a zzd_attr() routine
  1079. to release the resources when the attribute is deleted.
  1080.  
  1081. 68.  Attributes go out of scope when the rule or sub-rule that defines
  1082. them is exited.  Don't try to pass them to an outer rule or a sibling
  1083. rule.  The only exception is  $0 which may be passed back to the containing
  1084. rule as a return argument.  However, if the attribute contains a pointer
  1085. which is copied (e.g. pccts/h/charptr.c) then extra caution is required
  1086. because of the actions of zzd_attr().  For C++ users this should be
  1087. implemented in the class copy constructor. The version of pccts/h/charptr.*
  1088. distributed with pccts does not use C++ features.  See the next item for
  1089. more information.
  1090.  
  1091. 69.  The pccts/h/charptr.c routines use a pointer to a string.  The string
  1092. itself will go out of scope when the rule or sub-rule is exited.  Why ?
  1093. The string is copied to the heap when ANTLR calls the routine zzcr_attr()
  1094. supplied by charptr.c - however ANTLR also calls the charptr.c supplied
  1095. routine zzd_attr() (which frees the allocated string) as soon as the rule or
  1096. sub-rule exits.  The result is that in order to pass charptr.c strings to
  1097. outer rules (for instance to $0) it is necessary to make an independent
  1098. copy of the string using strdup or else zero the pointer to prevent its
  1099. deallocation.
  1100.  
  1101.                                                                      Page 23
  1102.  
  1103. 70.  To initialize $0 of a sub-rule use a construct like the following:
  1104.  
  1105.         decl : typeID
  1106.                Var      <<$2.type = $1;>>
  1107.                ( "," Var  <<$2.type = $0;>>)*[$1]
  1108.                                              ****       <--------------
  1109.  
  1110.                      See section 4.1.6.1 (page 29) of the 1.00 manual
  1111.  
  1112. 71.  One can use the zzdef0() macro to define a standard method for
  1113. initializing $0 of a rule or sub-rule.  If the macro is defined it is
  1114. invoked as zzdef0(&($0)).
  1115.  
  1116.      See section 4.1.6.1 (page 29) of the 1.00 manual
  1117.  
  1118. I believe that for C++ users this would be handled by the class constructor.
  1119.  
  1120. 72.  If you construct temporary attributes in the middle of the
  1121. recognition of a rule, remember to deallocate the structure should the
  1122. rule fail.  The code for failure goes after the ";" and before the next
  1123. rule.  For this reason it is sometimes desirable to defer some processing
  1124. until the rule is recognized rather than the most convenient place.
  1125.  
  1126.         #include "pccts/h/charptr.h"
  1127.  
  1128.         ;statement!
  1129.                 : <<char *label=0;>>
  1130.                   {ID COLON  <<label=MYstrdup($1);>> }
  1131.                          statement_without_label
  1132.                                 <<#0=#(#[T_statement,label],#2);
  1133.                                   if (label!=0) free(label);
  1134.                                         // AST #1 is undefined
  1135.                                         // AST #2 is returned by
  1136.                                         //   statement_without_label
  1137.                                 >>
  1138.         ;<<if (label !=0) free(label);>>
  1139.  
  1140. In the above example attributes are handled by charptr.*.  Readers of this
  1141. note have been warned earlier about its dangers.  The routine I have
  1142. written to construct ASTs from attributes (invoked by #[int,char *]) knows
  1143. about this behavior and automatically makes a copy of the character string
  1144. when it constructs the AST.  This makes the copy created by the explicit
  1145. call to MYstrdup redundant once the AST has been constructed.  If the call
  1146. to "statement_without_label" fails then the temporary copy must be
  1147. deallocated.
  1148.                                                                      Page 24
  1149.  
  1150. ===============================================================================
  1151. Section on ASTs
  1152. -------------------------------------------------------------------------------
  1153. 73.  If you define a zzcr_ast() or zzmk_ast() which allocates resources
  1154. such as strings from the heap don't forget to define a zzd_ast() routine
  1155. to release the resources when the AST is deleted.  For C++ users this
  1156. should be implemented as part of the class destructor.
  1157.  
  1158. 74.  If you construct temporary ASTs in the middle of the recognition of a
  1159. rule, remember to deallocate the structure should the rule fail.  The code
  1160. for failure goes after the ";" and before the next rule.  For this reason
  1161. it is sometimes desirable to defer some processing until the rule is
  1162. recognized rather than the most appropriate place.  For C++ users this
  1163. might be implemented as part of the class destructor.
  1164.  
  1165. If the temporary is an AST returned by a called rule then you'll probably
  1166. have to call zzfree_ast() to release the entire AST tree.  Consider
  1167. the following example:
  1168.  
  1169.    obj_name!                                                   /* a1  */
  1170.         : <<AST *node=0;>>                                     /* a2  */
  1171.           class_name <<node=#1;>>                              /* a3  */
  1172.                      (                                         /* a4  */
  1173.                        () /* empty */                          /* a5  */
  1174.                                 <<#0=node;node=0;>>            /* a6  */
  1175.                        | COLON_COLON follows_dot_class[node]   /* a7  */
  1176.                                 <<#0=#2;node=0;>>              /* a8  */
  1177.                      )                                         /* a9  */
  1178.           .........                                            /* a10 */
  1179.                                                                /* a11 */
  1180.          ; <<if (node!=0) zzfree_ast(node);>>                  /* a12 */
  1181.  
  1182. In this case "class_name" may return a full AST tree (not a trivial tree)
  1183. because of information required to represent template classes (e.g.
  1184. dictionary<int,1000> is a "class_name").  This tree ("node") is passed to
  1185. another rule ("follows_dot_class") which uses it to construct another AST
  1186. tree which incorporates it.  If "follows_dot_class" succeeds then node is
  1187. set to 0 (lines a6 or a8) because the tree is now referenced via #2.  If
  1188. "follows_dot_class" fails then the entire tree created by class_name must
  1189. be deallocated (line a12).  The temporary "node" must be used because there
  1190. is no convenient way (such as #1.1) to refer to class_name from within the
  1191. sub-rule.
  1192.  
  1193. Please note the use of an empty sub-rule ("()" on line a5) to avoid the nasty
  1194. init-action problem mentioned earlier.
  1195.  
  1196. 75.  Example 6 shows debugging code to help locate ASTs that were created
  1197. but never deleted.
  1198.  
  1199. 76.  If you want to place prototypes for routines that have an AST
  1200. as an argument in the #header directive you should explicitly
  1201. #include "ast.h" after the #define AST_FIELDS and before any references
  1202. to AST:
  1203.  
  1204.         #define AST_FIELDS int token;char *text;
  1205.         #include "ast.h"
  1206.         #define zzcr_ast(ast,attr,tok,astText) \
  1207.                 create_ast(ast,attr,tok,text)
  1208.         void create_ast (AST *ast,Attr *attr,int tok,char *text);
  1209.  
  1210.                                                                      Page 25
  1211.  
  1212. 77.  The make-a-root operator for ASTs ("^") can be applied only to
  1213. terminals.  (This includes items identified in #token ,#tokclass, and
  1214. #tokdef statements). I think this is because a child rule might return a
  1215. tree rather than a single AST.  If it did then it could not be made into a
  1216. root as it is already a root and the corresponding fields of the structure
  1217. are already in use.  To make an AST returned by a called rule a root use
  1218. the expression: #(root-rule sibling1 sibling2 sibling3).
  1219.  
  1220.         add !         :  expr ("\+"^ expr) ;    // Is ok
  1221.  
  1222.         addOperator ! :  expr (AddOp expr)      // Is NOT ok
  1223.         addOp         : "\+" | "-";             //
  1224.  
  1225. Example 2 describes a workaround for this restriction.
  1226.  
  1227. 78.  Because it is not possible to use an already constructed AST tree
  1228. as the root of a new tree (unless it's a trivial tree with no children)
  1229. one should be suspicious of any constructs like the following:
  1230.  
  1231.         rule! : ........ <<#0=#(#1,...)...;>>
  1232.                                 ** <=====================
  1233.  
  1234. If #1 is a non-trivial tree its existing children will be lost when the
  1235. new tree is constructed for assignment to #0.
  1236.  
  1237. 79.  Do not assign to #0 of a rule unless automatic construction of ASTs
  1238. has been disabled using the "!" operator:
  1239.  
  1240.                 a! : x y z <<#0=#(#1 #2 #3);>>  // ok
  1241.                 a  : x y z <<#0=#(#1 #2 #3);>>  // NOT ok
  1242.  
  1243. The reason for the restriction is that assignment to #0 will cause any
  1244. ASTs pointed to by #0 to be lost when the pointer is overwritten.
  1245.  
  1246. The stated restriction is somewhat stronger than necessary.  You can
  1247. assign to #0 even when using automated AST construction, if the old
  1248. tree pointed to by #0 is part of the new tree constructed by #(...).
  1249. For example:
  1250.  
  1251.         #token COMMA    ","
  1252.         #token STMT_LIST
  1253.  
  1254.         stmt_list: stmt (COMMA stmt)*  <<#0=#(#[STMT_LIST],#0);>>
  1255.  
  1256. The automatically constructed tree pointed to by #0 is just put at the
  1257. end of the new list, so nothing is lost.
  1258.  
  1259. If you reassign to #0 in the middle of the rule, automatic tree
  1260. construction will result in the addition of remaining elements at the end
  1261. of the new tree.  This is not recommended by TJP.
  1262.  
  1263. Special care must be used when combining the make-as-root operator
  1264. (e.g. rule: expr OP^ expr) with this transgression (assignment to #0 when
  1265. automatic tree construction is selected).
  1266.  
  1267.                                                                      Page 26
  1268.  
  1269. 80.  Even when automatic construction of ASTs is turned off in a rule the
  1270. called rules still return the ASTs that they constructed.  The same applies
  1271. when the "!" operator is applied to a called rule.  This is hard to
  1272. believe when one sees a rule like the following:
  1273.  
  1274.         rule: a! b! c!
  1275.  
  1276. generate (in part) a sequence of operations like:
  1277.  
  1278.         _ast = NULL; a(&_ast);
  1279.         _ast = NULL; b(&_ast);
  1280.         _ast = NULL; c(&_ast);
  1281.  
  1282. It appears that the AST pointer is being assigned to a temporary where it
  1283. becomes inaccessible.  This is not the case at all. The called rule is
  1284. responsible for placing a pointer to the AST which is constructed onto a
  1285. stack of AST pointers.  The stack of AST pointers is normally in global
  1286. scope with ZZAST_STACKSIZE elements.
  1287.  
  1288. (The "!" operator simply inhibits the automatic construction of the
  1289. AST trees.  It does not prevent the construction of the ASTs themselves.
  1290. When calling a rule which constructs ASTs and not using the result one
  1291. must destroy the constructed AST using zzfree_ast() in order to avoid a
  1292. memory leak.  See Example 6 below for code which aids in tracking lost
  1293. ASTs).
  1294.  
  1295. Consider the following examples (using the list notation of page 45 of
  1296. the 1.00 manual):
  1297.  
  1298.   a: A;
  1299.   b: B;
  1300.   c: C;
  1301.  
  1302.   #token T_abc_node
  1303.  
  1304.   rule   : a b c ;   <<;>>                   /* AST list (0 A B C) without root */
  1305.   rule ! : a b c     <<#0=#(0,#1,#2,#3);>>   /* AST list (0 A B C) without root */
  1306.   rule   : a! b! c!  <<#0=#(0,#1,#2,#3);>>   /* AST list (0 A B C) without root */
  1307.   rule   : a^ b c                            /* AST tree (A B C) with root A    */
  1308.   rule ! : a b c     <<#0=#(#1,#2,#3);>>     /* AST tree (A B C) with root A    */
  1309.  
  1310.   rule ! : a b c     <<#0=#(#[T_abc_node,0],#1,#2,#3);>>
  1311.                                              /* AST tree (T_abc_node A B C)     */
  1312.                                              /*   with root T_abc_node          */
  1313.   rule   : a b c     <<#0=#(#[T_abc_node,0],#0);>>          /* the same as above */
  1314.   rule   : a! b! c!  <<#0=#(#[T_abc_node,0],#1,#2,#3);>>    /* the same as above */
  1315.  
  1316.   rule ! : a b c     <<#0=#(toAST(T_abc_node),#1,#2,#3);>>  /* the same as above */
  1317.   rule   : a b c     <<#0=#(toAST(T_abc_node),#0);>>        /* the same as above */
  1318.   rule   : a! b! c!  <<#0=#(toAST(T_abc_node),#1,#2,#3);>>  /* the same as above */
  1319.  
  1320. The routine "toAST()" calls zzmk_ast() to construct an AST given the token number.
  1321. For a typical version of zzmk_ast() it would look something like the following:
  1322.  
  1323.         AST * toAST (int tokenID) {
  1324.            return zzmk_ast (zzastnew(),tokenID,NULL);
  1325.         }
  1326.  
  1327. I find toAST() more convenient than passing the extra arguments to zzmk_ast()
  1328. using a construct like #[T_abc_node,0] or writing zzmk_ast() with varargs.
  1329. Using varargs defeats most forms of inter-procedural type checking (unless you
  1330. are using C++ which allows overloaded function names).
  1331.  
  1332.                                                                      Page 27
  1333.  
  1334. 81.  If you use ASTs you have to pass a root AST to ANTLR.
  1335.  
  1336.                 AST     *root=NULL;
  1337.         again:
  1338.                 ANTLR (start(&root),stdin);
  1339.                 walk_the_tree(root);
  1340.                 zzfree_ast(root);
  1341.                 root=NULL;
  1342.                 goto again;
  1343.  
  1344. 82.  zzfree_ast(AST *tree) will recursively descend the AST tree and free
  1345. all sub-trees.  The user should supply a routine zzd_ast()  to free any
  1346. resources used by a single node - such as pointers to character strings
  1347. allocated on the heap.  See Example 2 on associativity and precedence.
  1348.  
  1349. 83.  AST elements in rules are assigned numbers in the same fashion as
  1350. attributes with three exceptions:
  1351.  
  1352.      1. A hole is left in the sequence when sub-rules are encountered.
  1353.         (e.g. "(...)+", "(...)*", and "{...}").
  1354.      2. #0 is the AST of the named rule, not the sub-rule - see the next item
  1355.      3. There is nothing analogous to $i.j notation (which allows one
  1356.         to refer to attributes from earlier in the rule).  In other words,
  1357.         you can't use #i.j notation to refer to an AST created earlier
  1358.         in the rule.
  1359.  
  1360.                 There are plans to add notation similar to Sorcerer's
  1361.                 tagged elements, but this will not appear for a while.
  1362.                 (24-Aug-94).  It is not part of version 1.22.
  1363.  
  1364. Consider the following example:
  1365.  
  1366.      a : b              // B is #1 for the rule
  1367.          (c d)*         // C is #1 when scope is inside the sub-rule
  1368.                         // D is #2 when scope is inside the sub-rule
  1369.                         //   You may *NOT* refer to b as #1.1
  1370.          e              // E is #3 for the rule
  1371.                         // There is NO #2 for the rule
  1372.  
  1373. 84.  The expression #0 refers to the AST of the named rule.  Thus it is
  1374. a misnomer and (for consistentcy) should probably have been named ## or #$.
  1375. There is nothing equivalent to $0 for ASTs.  This is probably because
  1376. sub-rules aren't assigned AST numbers in a rule.  See above.
  1377.  
  1378.                                                                      Page 28
  1379.  
  1380. 85.  Associativity and precedence of operations is determined by nesting
  1381. of rules.  In the example below "=" associates to the right and has the
  1382. lowest precedence.  Operators "+" and "*" associate to the left with "*"
  1383. having the highest precedence.
  1384.  
  1385.         expr0   : expr1 {"=" expr0};
  1386.         expr1   : expr2 ("\+" expr2)*;
  1387.         expr2   : expr3 ("\*" expr3)*;
  1388.         expr3   : ID;
  1389.  
  1390. In Example 2 the zzpre_ast() routine is used to walk all the AST nodes.
  1391. The AST nodes are numbered during creation so that one can see the order in
  1392. which they are created and the order in which they are deleted.  Do not
  1393. confuse the "#" in the sample output with the AST numbers used to refer to
  1394. elements of a rule in the action part of a the rule.  The "#" in the
  1395. sample output are just to make it simpler to match elements of the
  1396. expression tree with the order in which zzd_ast() is called for each node in
  1397. the tree.
  1398.  
  1399. 86.  If the make-as-root operator were NOT used in the rules:
  1400.  
  1401.         ;expr0  : expr1 {"=" expr0}
  1402.         ;expr1  : expr2 ("\+" expr2)*
  1403.         ;expr2  : expr3 ("\*" expr3)*
  1404.         ;expr3  : ID
  1405.  
  1406.     With input:
  1407.  
  1408.         a+b*c
  1409.  
  1410.     The output would be:
  1411.  
  1412.          a <#1>  \+ <#2>  b <#3>  \* <#4>  c <#5>  NEWLINE <#6>
  1413.  
  1414.         zzd_ast called for <node #6>
  1415.         zzd_ast called for <node #5>
  1416.         zzd_ast called for <node #4>
  1417.         zzd_ast called for <node #3>
  1418.         zzd_ast called for <node #2>
  1419.         zzd_ast called for <node #1>
  1420.  
  1421.                                                                      Page 29
  1422.  
  1423. 87.  Suppose that one wanted to replace the terminal "+" with the rule:
  1424.  
  1425.         addOp  : "\+" | "-" ;
  1426.  
  1427. Then one would be unable to use the "make-as-root" operator because it can
  1428. be applied only to terminals.
  1429.  
  1430. There are two workarounds.  The #tokclass feature allows one to write:
  1431.  
  1432.         #tokclass AddOp { "\+" "\-"}
  1433.  
  1434. A #tokclass identifier may be used in a rule wherever a simple #token
  1435. identifier may be used.
  1436.  
  1437. The other workaround is much more complicated:
  1438.  
  1439.         expr    : (expr0 NEWLINE)
  1440.         ;expr0  : expr1 {"="^ expr0}
  1441.         ;expr1! : expr2 <<#0=#1;>>
  1442.                         (addOp expr2  <<#0=#(#1,#0,#2);>> )*
  1443.         ;expr2  : expr3 ("\*"^ expr3)*
  1444.         ;expr3  : ID
  1445.         ;addOp  : "\+" | "\-"
  1446.  
  1447.      With input:
  1448.  
  1449.         a-b-c
  1450.  
  1451.      The output is:
  1452.  
  1453.         ( \- <#4> ( \- <#2>  a <#1>  b <#3> ) c <#5> ) NEWLINE <#6>
  1454.  
  1455. The "!" for rule "expr1" disables automatic constructions of ASTs in the
  1456. rule.  This allows one to manipulate #0 manually.  If the expression had
  1457. no addition operator then the sub-rule "(addOp expr)*" would not be
  1458. executed and #0 will be assigned the AST constructed by rule expr2 (i.e.
  1459. AST #1).  However if there is an addOp present then each time the sub-rule
  1460. is rescanned due to the "(...)*" the current tree in #0 is placed as the
  1461. first of two siblings underneath a new tree.  This new tree has the AST
  1462. returned by addOp (AST #1 of the addOp sub-rule) as the root.
  1463.  
  1464. 88.  There is an option for doubly linked ASTs in the module ast.c. It is
  1465. controlled by #define zzAST_DOUBLE.  Even with zzAST_DOUBLE only the right
  1466. and down fields are filled while the AST tree is constructed.  Once the tree
  1467. is constructed the user must call the routine zzdouble_link(tree,NULL,NULL) to
  1468. traverse the tree and fill in the left and up fields. See page 12 of the
  1469. 1.06 manual for more information.
  1470.  
  1471. 89.  If a rule which creates an AST is called and the result is not
  1472. linked into the tree being constructed then zzd_ast() will not be called
  1473. to release the resources used by the rule.  Prior to version 1.20
  1474. this was especially important when rules were used in syntactic predicates.
  1475. Versions >= 1.20 bypasses construction of all ASTs during guess mode.
  1476.                                                                      Page 30
  1477.  
  1478. ===============================================================================
  1479. Section on Semantic Predicates
  1480. -------------------------------------------------------------------------------
  1481. 90.  There is a bug in 1.1x and 1.2x which prevents semantic predicates
  1482. from including string literals.  The predicate is incorrectly
  1483. "string-ized" in the call to zzfailed_predicate.
  1484.  
  1485.                 rule:  <<containsCharacter("!@#$%^&*",LATEXT(1))>>?  ID
  1486.                                         /*  Will not work */
  1487.  
  1488. The workaround is to place the literal in a string constant and use
  1489. the variable name.
  1490.  
  1491. 91.  There is a bug in 1.1x and 1.2x which prevents semantic predicates from
  1492. crossing lines unless one uses an escaped newline.
  1493.  
  1494.                 rule: <<do_test();\     /*** Note escaped newline ***/
  1495.                         this_works_in_120)>>? x y z;
  1496.  
  1497. 92.  Semantic predicates are enclosed in "<<... >>?"  but because they are
  1498. inside "if" statements they normally do not end with a ";" - unlike other
  1499. code enclosed in "<<...>>" in ANTLR.
  1500.  
  1501. 93.  Semantic predicates which are not the first element in the rule or
  1502. sub-rule become "validation predicates" and are not used for prediction.
  1503. After all, if there are no alternatives, then there is no need for
  1504. prediction - and alternatives exist only at the left edge of rules
  1505. and sub-rules.  Even if the semantic predicates are on the left edge it
  1506. is no guarantee that it will be part of the prediction expression.
  1507. Consider the following two examples:
  1508.  
  1509.         a  :  << LA(1)==ID ? propX(LATEXT(1)) : 1 >>?  ID glob  /* a1 */
  1510.            |  ID glob                                           /* a2 */
  1511.            ;
  1512.         b  :  << LA(1)==ID ? propX(LATEXT(1)) : 1 >>?  ID glob  /* b1 */
  1513.            |  NUMBER glob                                       /* b2 */
  1514.            ;
  1515.  
  1516. Rule a requires the semantic predicate to disambiguate alternatives
  1517. a1 and a2 because the rules are otherwise identical.  Rule b has a
  1518. token type of NUMBER in alternative b2 so it can be distinguished from
  1519. b1 without evaluation of the semantic predicate during prediction.  In
  1520. both cases the semantic predicate will also be evaluated inside the rule.
  1521.  
  1522. When the tokens which can follow a rule allow ANTLR to disambiguate the
  1523. expression without resort to semantic predicates ANTLR may not evaluate
  1524. the semantic predicate in the prediction code.  For example:
  1525.  
  1526.         simple_func   : <<LA(1)==ID ? isSimpleFunc(LATEXT(1)) : 1>>? ID
  1527.         complex_func  : <<LA(1)==ID ? isComplexFunc(LATEXT(1)) : 1>>? ID
  1528.  
  1529.         function_call : "("  ")"
  1530.  
  1531.         func : simple_func  function_call
  1532.              | complex_func "." ID function_call
  1533.  
  1534. In this case, a "simple_func" MUST be followed by a "(", and a
  1535. "complex_func" MUST be followed by a ".", so it is unnecessary to evaluate
  1536. the semantic predicates in order to predict which of the alternative to
  1537. use.  A simple test of the lookahead tokens is sufficient. As stated
  1538. before, the semantic predicates will still be used to validate the rule.
  1539.  
  1540.                                                                      Page 31
  1541.  
  1542. 94.  Suppose that the requirement that all semantic predicates which are
  1543. used in prediction expressions must appear at the left hand edge of a rule
  1544. were lifted?  Consider the following code segment:
  1545.  
  1546.         cast_expr                          /* a1  */
  1547.             : LP typedef RP cast_expr      /* a2  */
  1548.             | expr13                       /* a3  */
  1549.         ;expr13                            /* a4  */
  1550.             : id_name                      /* a5  */
  1551.             | LP cast_expr RP              /* a6  */
  1552.         ;typedef                           /* a7  */
  1553.             : <<LA(1)==ID ? isTypedefName(LATEXT(1)) : 1 >>? ID    /* a8  */
  1554.         ;id_name                           /* a9  */
  1555.             : ID                           /* a10 */
  1556.  
  1557. Now consider the token sequences:
  1558.  
  1559.         Token:  #1           #2               #3   #4
  1560.                 --   -----------------------  --   --
  1561.                 "("  ID-which-is-typedef     ")"   ID
  1562.                 "("  ID-which-is-NOT-typedef ")"
  1563.  
  1564. Were the semantic predicate at line a8 hoisted to predict which alternative
  1565. of cast_expr to use (a2 or a3) the program would use the wrong lookahead
  1566. token (LA(1) and LATEXT(1)) rather than LA(2) and LATEXT(2) to check for an
  1567. ID which satisfies "isTypedefName()".  This is because it is preceded by a
  1568. "(".   This problem could perhaps be solved by application of sufficient
  1569. ingenuity, however, in the meantime the solution is to rewrite the rules
  1570. so as to move the decision point to the left edge of the production.
  1571.  
  1572. First perform in-line expansion of expr13 (line a3) in cast_expr:
  1573.  
  1574.         cast_expr                          /* b1 */
  1575.             : LP typedef RP cast_expr      /* b2 */
  1576.             | id_name                      /* b3 */
  1577.             | LP cast_expr RP              /* b4 */
  1578.  
  1579. Secondly, move the alternatives (in cast_expr) beginning with LP to a
  1580. separate rule so that "typedef" and "cast_expr" will be on the left edge:
  1581.  
  1582.         cast_expr                          /* c1  */
  1583.             : LP cast_expr_suffix          /* c2  */
  1584.             | id_name                      /* c3  */
  1585.         ;cast_expr_suffix                  /* c4  */
  1586.             : typedef RP cast_expr         /* c5  */
  1587.             | cast_expr RP                 /* c6  */
  1588.         ;typedef                           /* c7  */
  1589.             : <<LA(1)==ID ? isTypedefName(LATEXT(1)) : 1 >>? ID    /* c8  */
  1590.         ;id_name                           /* c9  */
  1591.             : ID                           /* c10 */
  1592.  
  1593. This will result in the desired treatment of the semantic predicate to
  1594. choose from alternatives c5 and c6.
  1595.  
  1596.                                                                      Page 32
  1597.  
  1598. 95.  Validation predicates are evaluated by the parser.  If they fail a
  1599. call to zzfailed_predicate(string) is made.  To disable the message
  1600. redefine the macro zzfailed_predicate(string) or use the optional
  1601. "failed predicate" action which is enclosed in "[" and "]" and follows
  1602. immediately after the predicate:
  1603.  
  1604.         a : <<LA(1)==ID ?
  1605.               isTypedef(LATEXT(1)) : 1>>?[printf("Not a typedef\n");]
  1606.  
  1607. 96.  An expression in a semantic predicate (e.g. <<isFunc()>>? ) should not
  1608. have side-effects. If there is no match then the rest of the rule using the
  1609. semantic predicate won't be executed.
  1610.  
  1611.                                                                      Page 33
  1612.  
  1613. 97.  What is the "context" of a semantic predicate ?  Answer due to TJP:
  1614.  
  1615. The context of a predicate is the set of k-strings (comprised of lookahead
  1616. symbols) that can be matched following the execution of a predicate.  For
  1617. example,
  1618.  
  1619.         a : <<p>>? alpha ;
  1620.  
  1621. The context of "p" is LOOK(alpha) where LOOK(alpha) is the set of
  1622. lookahead k-strings for alpha.
  1623.  
  1624. Normally, one should compute the context for ANTLR (manually) because
  1625. ANTLR is not smart enough to know the nature of your predicate and does not
  1626. know how much context information is needed; it's conservative and tries
  1627. to compute full LL(k) lookahead.  Normally, you only need one token:
  1628.  
  1629.         class_name: <<isClass(LATEXT(1))>>? ID ;
  1630.  
  1631. This example is incomplete, the predicate should really be:
  1632.  
  1633.         class_name: <<LA(1)==ID ? isClass(LATEXT(1)) : 1>>? ID ;
  1634.  
  1635. This says, "I can tell you something if you have an ID, otherwise
  1636. just assume that the rule is semantically valid."  This only makes a
  1637. difference if the predicate is *hoisted* out of the rule.  Here is an
  1638. example that won't work because it doesn't have context check in the
  1639. predicates:
  1640.  
  1641.         a   : ( class_name | NUM )
  1642.             | type_name
  1643.             ;
  1644.  
  1645.         class_name : <<isClass(LATEXT(1))>>? ID ;
  1646.  
  1647.         type_name :  <<isType(LATEXT(1))>>? ID ;
  1648.  
  1649. The prediction for production one of rule "a" will be:
  1650.  
  1651.         if ( LA(1) in { ID, NUM } && isClass(LATEXT(1)) ) { ...
  1652.  
  1653. Clearly, NUM will never satisfy isClass(), so the production will never
  1654. match.
  1655.  
  1656. When you ask ANTLR to compute context, it can check for missing predicates.
  1657. With -prc on, for this grammar:
  1658.  
  1659.         a   : b
  1660.             | <<isVar(LATEXT(1))>>?      ID
  1661.             | <<isPositive(LATEXT(1))>>? NUM
  1662.             ;
  1663.  
  1664.         b   : <<isType(LATEXT(1))>>?     ID
  1665.             |                            NUM
  1666.             ;
  1667.  
  1668. ANTLR reports:
  1669.  
  1670.         warning alt 1 of rule itself has no predicate to resolve
  1671.                                                  ambiguity upon \{ NUM \}
  1672.  
  1673.                                                                      Page 34
  1674.  
  1675. 98.  A documented restriction of ANTLR is the inability to hoist multiple
  1676. semantic predicates.  However, no error message is given when one attempts
  1677. this.  When compiled with k=1 and ck=2 this generates inappropriate code
  1678. in "statement" when attempting to predict "expr":
  1679.  
  1680.         #header <<
  1681.  
  1682.         #include "charbuf.h"
  1683.  
  1684.         int     istypedefName (char *);
  1685.         int     isCommand (char *);
  1686.  
  1687.         >>
  1688.  
  1689.         #token  BARK
  1690.         #token  GROWL
  1691.         #token  ID
  1692.  
  1693.         statement
  1694.                 : expr
  1695.                 | declaration
  1696.         ;expr
  1697.                 : commandName BARK
  1698.                 | typedefName GROWL
  1699.         ;declaration
  1700.                 : typedefName BARK
  1701.         ;typedefName
  1702.                 : <<LA(1)==ID ? istypedefName(LATEXT(1)) : 1>>? ID
  1703.         ;commandName
  1704.                 : <<LA(1)==ID ? isCommand(LATEXT(1)) : 1>>? ID
  1705.         ;
  1706.  
  1707. The generated code resembles the following:
  1708.  
  1709.         void statement()
  1710.         {
  1711.                 if ( (LA(1)==ID) &&
  1712.                      (LA(2)==BARK || LA(2)==GROWL) &&
  1713.                      (  (LA(1)==ID ? isCommand(LATEXT(1)) : 1) ||
  1714.                         (LA(1)==ID ? istypedefName(LATEXT(1)) : 1)) ) {
  1715.                                 expr();
  1716.                 } else {
  1717.                   if ( (LA(1)==ID) &&
  1718.                        (LA(2)==BARK) &&
  1719.                        (LA(1)==ID ? istypedefName(LATEXT(1)) : 1)) ) {
  1720.                                 declaration();
  1721.                 } ...
  1722.  
  1723. The problem is that "<typdefname> BARK" will be passed to expr() rather
  1724. than declaration().
  1725.  
  1726. Some help is obtained by using leading actions to inhibit hoisting as
  1727. described in the next notes.  However, omitting all semantic predicates
  1728. in the prediction expression doesn't help if one requires them to predict
  1729. the rule.
  1730.  
  1731.                                                                      Page 35
  1732.  
  1733. 99.  Leading actions will inhibit the hoisting of semantic predicates into
  1734. the prediction of rules.
  1735.  
  1736.         expr_rhs
  1737.                 : <<;>> <<>>  expr0
  1738.                 | command
  1739.  
  1740. See the section on known bugs for a more complete example.
  1741.  
  1742. 100.  When using semantic predicates in ANTLR is is *IMPORTANT* to
  1743. understand what the "-prc on" ("predicate context computation")
  1744. option does and what "-prc off" doesn't do.  Consider the following
  1745. example:
  1746.  
  1747.                 +------------------------------------------------------+
  1748.                 | Note:  All examples in this sub-section are based on |
  1749.                 | code generated with -k=1 and -ck=1.                  |
  1750.                 +------------------------------------------------------+
  1751.  
  1752.         expr    : upper
  1753.                 | lower
  1754.                 | number
  1755.                 ;
  1756.  
  1757.         upper   : <<isU(LATEXT(1))>>? ID ;
  1758.         lower   : <<isL(LATEXT(1))>>? ID ;
  1759.         number  : NUMBER ;
  1760.  
  1761. With "-prc on" ("-prc off" is the default) the code for expr() to predict
  1762. upper() would resemble:
  1763.  
  1764.       if (LA(1)==ID && isU(LATEXT(1)) && LA(1)==ID) {   /* a1  */
  1765.                 upper(zzSTR);                           /* a2  */
  1766.         }                                               /* a3  */
  1767.         else {                                          /* a4  */
  1768.                 if (LA(1)==ID && isL(LATEXT(1)) && LA(1)==ID) {  /* a5  */
  1769.                         lower(zzSTR);                   /* a6  */
  1770.                 }                                       /* a7  */
  1771.                 else {                                  /* a8  */
  1772.                         if (LA(1)==NUMBER) {            /* a9  */
  1773.                                 zzmatch(NUMBER);        /* a10 */
  1774.                         }                               /* a11 */
  1775.                         else                            /* a12 */
  1776.                                 {zzFAIL();goto fail;}   /* a13 */
  1777.                 }                                       /* a14 */
  1778.         } ...
  1779.         ...
  1780.  
  1781.         *******************************************************
  1782.         ***                                                 ***
  1783.         *** Starting with version 1.20:                     ***
  1784.         ***   Predicate tests appear AFTER lookahead tests  ***
  1785.         ***                                                 ***
  1786.         *******************************************************
  1787.  
  1788. Note that each test of LATEXT(i) is guarded by a test of the token type
  1789. (e.g. "LA(1)==ID && isU(LATEXT(1)").
  1790.                                                                      Page 36
  1791.  
  1792. With "-prc off" the code would resemble:
  1793.  
  1794.      if (isU(LATEXT(1)) && LA(1)==ID) {             /* b1  */
  1795.                 upper(zzSTR);                       /* b2  */
  1796.         }                                           /* b3  */
  1797.         else {                                      /* b4  */
  1798.                 if (isL(LATEXT(1)) && LA(1)==ID) {  /* b5  */
  1799.                         lower(zzSTR);               /* b6  */
  1800.                 }                                   /* b7  */
  1801.                 else {                              /* b8  */
  1802.                         if ( (LA(1)==NUMBER) ) {    /* b9  */
  1803.                                 zzmatch(NUMBER);    /* b10 */
  1804.                         }                           /* b11 */
  1805.                         else                        /* b12 */
  1806.                                 {zzFAIL();goto fail;}       /* b13 */
  1807.                 }                                   /* b14 */
  1808.         } ...
  1809.         ...
  1810.  
  1811. Thus when coding the grammar for use with "-prc off" it is necessary
  1812. to do something like:
  1813.  
  1814.         upper   : <<LA(1)==ID && isU(LATEXT(1))>>? ID ;
  1815.         lower   : <<LA(1)==ID && isL(LATEXT(1))>>? ID ;
  1816.  
  1817. This will make sure that if the token is of type NUMBER that it is not
  1818. passed to isU() or isL() when using "-prc off".
  1819.  
  1820. So, you say to yourself, "-prc on" is good and "-prc off" is bad. Wrong.
  1821.  
  1822. Consider the following slightly more complicated example in which the
  1823. first alternative of rule "expr" contains tokens of two different types:
  1824.  
  1825.         expr    : ( upper | NUMBER ) NUMBER
  1826.                 | lower
  1827.                 | ID
  1828.                 ;
  1829.  
  1830.         upper   : <<LA(1)==ID && isU(LATEXT(1))>>? ID ;
  1831.         lower   : <<LA(1)==ID && isL(LATEXT(1))>>? ID ;
  1832.         number  : NUMBER ;
  1833.  
  1834. With "-prc off" the code would resemble:
  1835.  
  1836.         ...
  1837.         {                                                 /* c1  */
  1838.         if (LA(1)==ID && isU(LATEXT(1)) &&                /* c2  */
  1839.              ( LA(1)==ID || LA(1)==NUMBER) ) {            /* c3  */
  1840.                 {                                         /* c4  */
  1841.                         if (LA(1)==ID) {                  /* c5  */
  1842.                                 upper(zzSTR);             /* c6  */
  1843.                         }                                 /* c7  */
  1844.                         else {                            /* c8  */
  1845.                                 if (LA(1)==NUMBER) {      /* c9  */
  1846.                                         zzmatch(NUMBER);  /* c10 */
  1847.                                 }                         /* c11 */
  1848.                                 else {zzFAIL();goto fail;}/* c12 */
  1849.                         }                                 /* c13 */
  1850.                 } ...
  1851.         ...
  1852.                                                                      Page 37
  1853.  
  1854. Note that if the token is a NUMBER (i.e. LA(1)==NUMBER) then the clause at
  1855. line c2 ("LA(1)==ID && ...") will always be false, which implies that the
  1856. test in the "if" statement (lines c2/c3) will always be false. (In other
  1857. words LA(1)==NUMBER implies LA(1)!=ID).  Thus the sub-rule for NUMBER at
  1858. line c9 can never be reached.
  1859.  
  1860. With "-prc on" essentially the same code is generated, although it
  1861. is not necessary to manually code a test for token type ID preceding
  1862. the call to "isU()".
  1863.  
  1864. The workaround is to to bypass the heart of the  predicate when
  1865. testing the wrong type of token.
  1866.  
  1867.         upper   : <<LA(1)==ID ? isU(LATEXT(1)) : 1>>? ID ;
  1868.         lower   : <<LA(1)==ID ? isL(LATEXT(1)) : 1>>? ID ;
  1869.  
  1870. Then with "-prc off" the code would resemble:
  1871.         ...
  1872.         {                                           /* d1  */
  1873.         if ( (LA(1)==ID ? isU(LATEXT(1)) : 1) &&    /* d2  */
  1874.                 (LA(1)==ID || LA(1)==NUMBER) ) {    /* d3  */
  1875.                 ...
  1876.         ...
  1877.  
  1878. With this correction the body of the "if" statement is now reachable
  1879. even if the token type is NUMBER - the "if" statement does what one
  1880. wants.
  1881.  
  1882. With "-prc on" the code would resemble:
  1883.  
  1884.         ...                                       /* e1 */
  1885.         if (LA(1)==ID &&                          /* e2 */
  1886.              (LA(1)==ID ? isU(LATEXT(1)) : 1) &&  /* e3 */
  1887.              (LA(1)==ID || LA(1)==NUMBER) ) {     /* e4 */
  1888.                 ...
  1889.         ...
  1890.  
  1891. Note that the problem of the unreachable "if" statement body has
  1892. reappeared because of the redundant test ("e2") added by the predicate
  1893. computation.
  1894.  
  1895. The lesson seems to be: when using rules which have alternatives which
  1896. are "visible" to ANTLR (within the lookahead distance) that have different
  1897. token types it is probably dangerous to use "-prc on".
  1898.  
  1899.                                                                      Page 38
  1900.  
  1901. 101.  You cannot use downward inheritance to pass parameters
  1902. to semantic predicates which are NOT validation predicates.  The
  1903. problem appears when the semantic predicate is hoisted into a
  1904. parent rule to predict which rule to call:
  1905.  
  1906. For instance:
  1907.  
  1908.         a :  b1 [flag]
  1909.           |  b2
  1910.           |  b3
  1911.  
  1912.         b1 [int flag]
  1913.           : <<LA(1)==ID && flag && hasPropertyABC (LATEXT(1))>>? ID ;
  1914.  
  1915.         b2 :
  1916.           : <<LA(1)==ID && hasPropertyXYZ (LATEXT(1))>>? ID ;
  1917.  
  1918.         b3 : ID ;
  1919.  
  1920. When the semantic predicate is evaluated within rule "a" to determine
  1921. whether to call b1, b2, or b3 the compiler will discover that there
  1922. is no variable named "flag" for procedure "a()".  If you are unlucky
  1923. enough to have a variable named "flag" in a() then you will have a
  1924. VERY difficult-to-find bug.
  1925.  
  1926. The -prc option has no effect on this behavior.
  1927.  
  1928. It is possible that an init-action will inhibit the hoisting of the
  1929. predicate and make this code work.  I have not verified this with
  1930. versions 1.2x.
  1931.  
  1932. 102.  Another reason why semantic predicates must not have side effects is
  1933. that when they are hoisted into a parent rule in order to decide which
  1934. rule to call they will be invoked twice: once as part of the prediction
  1935. and a second time as part of the validation of the rule.
  1936.  
  1937. Consider the example above of upper and lower.  When the input does
  1938. in fact match "upper" the routine isU() will be called twice: once inside
  1939. expr() to help predict which rule to call, and a second time in upper() to
  1940. validate the prediction.  If the second test fails the macro zzpred_fail()
  1941. is called.
  1942.  
  1943. As far as I can tell, there is no simple way to disable the use of a
  1944. semantic predicate for validation after it has been used for prediction.
  1945.  
  1946.                                                                      Page 39
  1947.  
  1948. 103.  I had a problem in which I needed to do a limited amount of
  1949. lookahead, but didn't want to use all the machinery of syntactic
  1950. predicates.  I found that I could enlarge the set of expressions accepted
  1951. by "expr" and then look at the AST created in order to determined what
  1952. rules could follow:
  1953.  
  1954.         cast_expr                                                 /* a1  */
  1955.                 : <<int isCast=0;>>                               /* a2  */
  1956.                                                                   /* a3  */
  1957.                 LP! predefined_type RP! cast_expr                 /* a4  */
  1958.                         <<#0=#(toAST(T_cast),#0);>>               /* a5  */
  1959.                 | LP! expr0 RP!                                   /* a6  */
  1960.                         <<if ((#2->token)==T_class_name) {        /* a7  */
  1961.                              isCast=1;                            /* a8  */
  1962.                           } else {                                /* a9  */
  1963.                              isCast=0;                            /* a10 */
  1964.                           };                                      /* a11 */
  1965.                         >>                                        /* a12 */
  1966.                         ( <<;>> <<isCast==1>>?                    /* a13 */
  1967.                                 <<printf ("\nIs cast expr\n");>>  /* a14 */
  1968.                                 cast_expr                         /* a15 */
  1969.                                 <<#0=#(toAST(T_cast),#0);>>       /* a16 */
  1970.                                                                   /* a17 */
  1971.                         | <<printf ("\nIs NOT cast expr\n");>>    /* a18 */
  1972.                                 () /* empty */                    /* a19 */
  1973.                         )                                         /* a20 */
  1974.                 | unary_expr                                      /* a21 */
  1975.  
  1976. Later on I gave up on this approach and decided to use syntactic
  1977. predicates anyway.  It not only solved this problem, but others
  1978. where it was more difficult to patch up the grammar.  I can't bring
  1979. myself to remove the example, though.
  1980.                                                                      Page 40
  1981.  
  1982. ===============================================================================
  1983. Section on Syntactic Predicates (also known as "Guess Mode")
  1984. -------------------------------------------------------------------------------
  1985. 104.  The terms "infinite lookahead", "guess mode","syntactic predicates"
  1986. are all equivalent.  Sometimes the term "backtracking" is used as well,
  1987. although " backtracking" can sometimes be used to discuss lexing and DLG
  1988. as well.  The term "syntactic predicate" emphasizes that is handled by the
  1989. parser. The term "guess mode" emphasizes that the parser may have to
  1990. backtrack.  The term "infinite lookahead" emphasizes the implementation in
  1991. ANTLR: the entire input is read, processed, and tokenized by DLG before
  1992. ANTLR begins parsing.
  1993.  
  1994. 105.  An expression in a syntactic predicate should not have side-effects.
  1995. If there is no match then the rule using the syntactic predicate won't be
  1996. executed.
  1997.  
  1998. 106.  When using syntactic predicates the entire input buffer is read and
  1999. tokenized by DLG before parsing by ANTLR begins.  If a "wrong" guess
  2000. requires that parsing be rewound to an earlier point all attributes
  2001. that were creating during the "guess" are destroyed and the parsing
  2002. begins again and it creates new attributes at it reparses the (previously)
  2003. tokenized input.
  2004.  
  2005. 107.  In infinite lookahead mode the line and column information is
  2006. hopelessly out-of-sync because zzline will contain the line number of
  2007. the last line of input - the entire input was parsed before
  2008. scanning was begun.  The line and column information is not restored
  2009. during backtracking.  To keep track of the line information in a meaningful
  2010. way one has to use the ZZINF_LINE macro which was added to pccts in version
  2011. 1.20.
  2012.  
  2013. Putting line and column information in a field of the attribute will not
  2014. help.  The attributes are created by ANTLR, not DLG, and when ANTLR
  2015. backtracks it destroys any attributes that were created in making the
  2016. incorrect guess.
  2017.  
  2018. 108.  As infinite lookahead mode causes the entire input to be scanned
  2019. by DLG before ANTLR begins parsing, one cannot depend on feedback from
  2020. the parser to the lexer to handle things like providing special token codes
  2021. for items which are in a symbol table (the "lex hack" for typedefs
  2022. in the C language).  Instead one MUST use semantic predicates which allow
  2023. for such decisions to be made by the parser.
  2024.  
  2025. 109.  One cannot use an interactive scanner (ANTLR -gk option) with the
  2026. ANTLR infinite lookahead and backtracking options (syntactic predicates).
  2027.  
  2028. 110.  An example of the need for syntactic predicates is the case where
  2029. relational expressions involving "<" and ">"  are enclosed in angle bracket
  2030. pairs.
  2031.  
  2032.         Relation:    a < b
  2033.         Array Index: b <i>
  2034.         Problem:     a < b<i>
  2035.                  vs. b < a>
  2036.  
  2037. I was going to make this into an extended example, but I haven't had
  2038. time yet.
  2039.  
  2040. 111. Version 1.20 fixes a problem in 1.10 in which ASTs were constructed
  2041. during guess mode.  In version 1.10 care had to be taken to deallocate the
  2042. ASTs that were created in the rules which were invoked in guess mode.
  2043.  
  2044.                                                                      Page 41
  2045.  
  2046. 112.  The following is an example of the use of syntactic predicates.
  2047.  
  2048.         program : ( s SEMI )* ;
  2049.  
  2050.         s       : ( ID EQUALS )? ID EQUALS e
  2051.                   | e
  2052.                   ;
  2053.  
  2054.         e       : t ( PLUS t | MINUS t )* ;
  2055.  
  2056.         t       : f ( TIMES f | DIV f )* ;
  2057.  
  2058.         f       : Num
  2059.                   | ID
  2060.                   | "\(" e "\)"
  2061.                   ;
  2062.  
  2063. When compiled with k=1:
  2064.  
  2065.         antlr -fe err.c -fh stdpccts.h -fl parser.dlg -ft tokens.h \
  2066.                  -fm mode.h -k 1 test.g
  2067.  
  2068. One gets the following warning:
  2069.  
  2070.    warning: alts 1 and 2 of the rule itself ambiguous upon { ID }
  2071.  
  2072. even though the manual suggests that this is okay.  The only problem is
  2073. that ANTLR 1.10 should NOT issue this error message unless the -w2 option
  2074. is selected.
  2075.  
  2076. Included with permission of S. Salters
  2077.                                                                      Page 42
  2078.  
  2079. ===============================================================================
  2080. Section on Inheritance
  2081. -------------------------------------------------------------------------------
  2082. 113.  A rule which uses upward inheritance:
  2083.  
  2084.         rule > [int result] :  x | y | z;
  2085.  
  2086. Is simply declaring a function which returns an "int" as a function
  2087. value.  If the function has more than one item passed via upward
  2088. inheritance then ANTLR creates a structure to hold the result and
  2089. then copies each component of the structure to the upward inheritance
  2090. variables.
  2091.  
  2092. 114.  When writing a rule that uses downward inheritance:
  2093.  
  2094.         rule [int *x] : r1 r2 r3
  2095.  
  2096. one should remember that the arguments passed via downward inheritance are
  2097. simply arguments to a function.  If one is using downward inheritance
  2098. syntax to pass results back to the caller (really upward inheritance !)
  2099. then it is necessary to pass the address of the variable which will receive
  2100. the result.
  2101.  
  2102. 115.  ANTLR is smart enough to combine the declaration for an AST with
  2103. the items declared via downward inheritance when constructing the
  2104. prototype for a function which uses both ASTs and downward inheritance.
  2105.                                                                      Page 43
  2106.  
  2107. ===============================================================================
  2108. Section on LA, LATEXT, NLA, and NLATEXT
  2109. -------------------------------------------------------------------------------
  2110. 116.  Need examples of LATEXT for various forms of lookahead.
  2111.  
  2112. ===============================================================================
  2113. Section on Prototypes
  2114. -------------------------------------------------------------------------------
  2115. 117.  Prototype for typical create_attr routine:
  2116.  
  2117.      #define zzcr_attr(attr,token,text) \
  2118.                 create_attr(attr,token,text)
  2119.  
  2120.      void create_attr (Attrib *attr,int token,char *text);
  2121.  
  2122. 118.  Prototype for a typical create_ast routine invoked to automatically
  2123. construct an AST from an attribute:
  2124.  
  2125.      #define zzcr_ast(ast,attr,tok,astText) \
  2126.           create_ast(ast,attr,tok,text)
  2127.  
  2128.      void create_ast (AST *ast,Attr *attr,int tok,char *text);
  2129.  
  2130. 119.  Prototype for a typical make_ast routine invoked by the #[...]
  2131. notation.
  2132.  
  2133.      AST *zzmk_ast (AST *ast,int token,char *text)
  2134.  
  2135. 120.  Prototype for a typical zzd_ast macro which is invoked when destroying
  2136. an AST node:
  2137.  
  2138.      #define zzd_ast(node) delete_ast(node)
  2139.  
  2140.      void delete_ast (AST * node);
  2141.  
  2142. 121.  Prototype for zzdef0 macro to initialize $0 of a rule:
  2143.  
  2144.      #define zzdef0(attr) define_attr_0 (attr)
  2145.  
  2146.      void define_attr_0 (Attrib *attr);
  2147.  
  2148. 122.  Prototype for ANTLR (these are actually macros):
  2149.  
  2150.      read from file:     void ANTLR   (void startRule(...),FILE *)
  2151.      read from string:   void ANTLRs  (void startRule(...),zzchar_t *)
  2152.      read from function: void ANTLRf  (void startRule(...),int (*)())
  2153.      read from file:     void ANTLRm
  2154.                           (void startRule(...),FILE *,int lexclass)
  2155.  
  2156.              In the call to ANTLRf the function behaves like getchar()
  2157.              in that it returns EOF (-1) to indicate end-of-file.
  2158.  
  2159.      If ASTs are used or there is downward or upward inheritance then the
  2160.      call to the startRule must pass these arguments:
  2161.  
  2162.                 AST     *root;
  2163.                 ANTLRf (startRule(&root),stdin);
  2164.                                                                      Page 44
  2165.  
  2166. ===============================================================================
  2167. Section on ANTLR/DLG Internals Routines That Might Be Useful
  2168. -------------------------------------------------------------------------------
  2169.                 ****************************
  2170.                 ****************************
  2171.                 **                        **
  2172.                 **  Use at your own risk  **
  2173.                 **                        **
  2174.                 ****************************
  2175.                 ****************************
  2176.  
  2177. 123.  static int zzauto - defined in dlgauto.h
  2178.  
  2179.      Current DLG mode.  This is used by zzmode() only.
  2180.  
  2181. 124.  void zzerr (char * s) defined in dlgauto.h
  2182.  
  2183.      Defaults to zzerrstd(char *s) in dlgauto.h
  2184.  
  2185.      Unless replaced by a user-written error reporting routine:
  2186.  
  2187.              fprintf(stderr,
  2188.                         "%s near line %d (text was '%s')\n",
  2189.                         ((s == NULL) ? "Lexical error" : s),
  2190.                         zzline,zzlextext);
  2191.  
  2192. 125.  static char zzebuf[70] defined in dlgauto.h
  2193.                                                                      Page 45
  2194.  
  2195. ===============================================================================
  2196. Section on Known Minor Bugs in pccts
  2197. -------------------------------------------------------------------------------
  2198. 126.  In the 8-Aug-94 distribution of version 1.21, line 434 of err.h
  2199. should be changed:
  2200.  
  2201.         from:   zzline = zzinf_line[zzinf_line];
  2202.         to:     zzline = zzinf_line[zzinf_labase];
  2203.  
  2204. Diagnosed (and fix) reported by Anders Sterholm (anvil@lysator.liu.se)
  2205.  
  2206. 127.  With version 1.20 (1-Apr-94) of ANTLR the -w2 switch will sometimes
  2207. cause items to be reported as lacking an associated regular expression when
  2208. they actually do have an associated regular expression.  Sometimes
  2209. #lexclass names and #tokclass names will also be reported.  This is
  2210. reported as fixed in 1.21.
  2211.  
  2212. 128.  The UPDATE.120 of (1-Apr-94) reports that there are problems in
  2213. combining guess mode and semantic predicates under some circumstances.
  2214.  
  2215. 129.  In version 1.20 there is a bug in the 1-Apr-94 distribution of
  2216. routine _zzsetmatch() which appears when used with ANTLR -gk (demand
  2217. lookahead.  This is reported as fixed in version 1.21.
  2218.  
  2219. 130.  In version 1.20 a rule which returns more than two arguments
  2220. (via upward inheritance) generates code which cannot be compiled by
  2221. a strict K&R compiler.  It is accepted by ANSI compilers, however.
  2222. This is reported as fixed in version 1.21.  Reported by Joachim Schrod
  2223. (schrod@iti.informatik.th-darmstadt.de).
  2224.  
  2225. 131.  There appears to be a bug in 1.20 and 1.21 when using syntactic
  2226. predicates.  Sometimes attributes are corrupted by backtracking when k=1
  2227. under a combination of circumstances which are difficult to describe. A
  2228. patch for this problem is reported in netnews note #421 and the problem
  2229. will be fixed in release 1.22.  This problem was reported by Sanjay
  2230. Ghemawat (Sanjay@lcs.mit.edu)
  2231.  
  2232.                                                                      Page 46
  2233.  
  2234. 132.  The following problem was first reported by Carle Patrice
  2235. (carle@litp.ibp.fr) in netnews note #347.  TJP describes the problem
  2236. in netnews note #428:
  2237.  
  2238.         It is related to lookahead computation for k=3 with a hoisted
  2239.         predicate.  I have reduced the error to this case:
  2240.  
  2241.         a : (A B | B C) | b ;
  2242.  
  2243.         b : <<pred-c>>? B B ;
  2244.  
  2245.         It did not compute the correct lookahead decision for
  2246.         alternative one in rule "a".  It should generate:
  2247.  
  2248.         if ( (LA(1)==A || LA(1)==B) && (LA(2)==B || LA(2)==C) &&
  2249.              !((LA(1)==B&&(LA(2)==B))) ) {
  2250.                 ...
  2251.         }
  2252.         else blah
  2253.  
  2254.     *NOT* simply:
  2255.  
  2256.         if ( (LA(1)==A || LA(1)==B) && (LA(2)==B || LA(2)==C) ) {
  2257.                 ...
  2258.         }
  2259.         else blah
  2260.  
  2261. This will be fixed in version 1.22.
  2262.  
  2263.                                                                      Page 47
  2264.  
  2265. 133.  In version 1.10 there was a bug in the hoisting of semantic
  2266. predicates when all alternatives of a rule had the same lookahead token.
  2267. I believe this has been fixed in versions >= 1.20. Consider the following
  2268. (compiled with -prc off -k 1 -ck 3):
  2269.  
  2270.         ;obj_name
  2271.                 : global_func_id
  2272.                 | simple_class SUFFIX_DOT
  2273.                 | ID
  2274.  
  2275.         ;simple_class
  2276.                 : <<(LA(1)==ID ? isClass(LATEXT(1)) : 1)>>? ID
  2277.  
  2278.         ;global_func_id
  2279.                 : <<(LA(1)==ID ? isFunction(LATEXT(1)) : 1)>>? ID
  2280.  
  2281. In version 1.2x the generated code resembles:
  2282.  
  2283.         void obj_name(void) {
  2284.                 if ( (LA(1)==ID) &&
  2285.                      (LA(1)==ID ? isFunction(LATEXT(1)) : 1)) ) {
  2286.                         global_func_id();
  2287.                 } else {
  2288.                         if ( (LA(1)==ID) &&
  2289.                              (LA(2)==SUFFIX_DOT) ) {
  2290.                         simple_class();
  2291.                 } else {
  2292.                         if ( (LA(1)==ID) ) {
  2293.                               zzmatch(ID);
  2294.                 ...
  2295.  
  2296. The workaround, previously, was to precede semantic predicates with an
  2297. action (such as "<<;>>") which inhibits hoisting into the prediction
  2298. expression.
  2299.                                                                      Page 48
  2300.  
  2301. #header
  2302. <<
  2303. #include "charptr.h"
  2304. >>
  2305.  
  2306. #token  QUESTION
  2307. #token  COMMA
  2308. #token  ID
  2309.  
  2310. #token  Eof     "@"
  2311.  
  2312. #token  SUFFIX_DOT
  2313.  
  2314. statement
  2315.         : (information_request)?
  2316.         | obj_name
  2317.  
  2318. ;information_request
  2319.         : QUESTION id_list ( QUESTION )*
  2320.         | id_list ( QUESTION )+
  2321.  
  2322. ;id_list
  2323.         : obj_name ( COMMA | obj_name )*
  2324.  
  2325. ;simple_class
  2326.         : <<(LA(1)==ID ? isClass(LATEXT(1)) : 1)>>? ID
  2327.  
  2328. ;global_func_id
  2329.         : <<(LA(1)==ID ? isFunction(LATEXT(1)) : 1)>>? ID
  2330.  
  2331. ;obj_name
  2332.         : <<;>> global_func_id
  2333.         | <<;>> simple_class SUFFIX_DOT
  2334.         | ID
  2335. ;
  2336.                                                                      Page 49
  2337.  
  2338. ===============================================================================
  2339. Ideas on the Construction of ASTs and their use with Sorcerer
  2340. -------------------------------------------------------------------------------
  2341. Consider the problem of a grammar which would normally require two
  2342. passes through the source code to properly analyze.  In some cases
  2343. it is convenient to perform a first pass which creates AST trees
  2344. and perform the second pass by analyzing the AST trees with Sorcerer.
  2345.  
  2346. 1) Define an AST node that contains the information you'll need in the
  2347. second pass.  For example,
  2348.  
  2349. /*
  2350.  * Parse trees are represented by an abstract-syntax-tree (AST)
  2351.  * (forward declare the pointer here). Refer to parse.h for description
  2352.  * of parse_info.
  2353.  */
  2354. typedef struct parse_struct *ast_ref;
  2355.  
  2356. /* parser attributes ($-symbols) & AST nodes */
  2357. typedef struct parse_struct *pinfo_ref;
  2358.  
  2359. /*
  2360.  * the parse structure is used to describe both attributes and
  2361.  * AST nodes
  2362.  */
  2363.  
  2364. struct parse_struct {
  2365.     pinfo_ref   right;             /* points to siblings */
  2366.     pinfo_ref   down;              /* points to children */
  2367.     int         token;             /* token number (see tokens.h) */
  2368.     char        *text;             /* input text */
  2369.     src_pos     pos;               /* position in source file */
  2370.     object_ref  obj;               /* object description (id's) */
  2371.     type_ref    typ;               /* type description (expr's) */
  2372.     const_value value;             /* value of a constant expression */
  2373.     } ;
  2374.  
  2375. /*
  2376.  * define Abstract Syntax Tree (AST) nodes
  2377.  */
  2378.  
  2379. /* ast_ref was forward-defined */
  2380. typedef struct parse_struct AST;
  2381.  
  2382. /*
  2383.  * the Pass-1 (parse phase) parse-attributes ($-variables)
  2384.  * have the same structure as an AST node.
  2385.  */
  2386. typedef struct parse_struct Attrib, *Attrib_ref;
  2387.  
  2388.  
  2389. In the code above, the parse-attribute was defined to have the same
  2390. structure as an AST node.  This isn't a requirement, but just makes it
  2391. easier to pass information produced in the first pass on to subsequent
  2392. passes.
  2393.                                                                      Page 50
  2394.  
  2395. 2) Have the first pass build a symbol table as it parses the input, perform
  2396. semantic checks, and build an AST.  Use the -gt (generate tree) option on
  2397. ANTLR, and override the automatically generated tree construction operations
  2398. as needed.  For example,
  2399.  
  2400. var_declare:
  2401.         << pvec_ref v_list;
  2402.            int i;
  2403.            boolean has_var_section = FALSE;
  2404.         >>
  2405.         VAR^
  2406.         (
  2407.         var_id_list > [v_list] COLON
  2408.           { extern_kw
  2409.             | static_kw
  2410.           }
  2411.         type
  2412.         <<
  2413.         for (i = 0; i < v_list->len; ++i) {
  2414.             object_ref v = (object_ref) v_list->val[i];
  2415.             define_var(v, $4.typ);
  2416.         }
  2417.         >>
  2418.           { ASSIGNMENT expr
  2419.             << mark_var_use(#2, VAR_RHS); >>
  2420.           }
  2421.         SEMI
  2422.         << free_pvec(v_list); >>
  2423.         )+
  2424.         ;
  2425. var_id_list > [pvec_ref v_list]:
  2426.         << object_ref this_var;
  2427.            $v_list = new_pvec();
  2428.         >>
  2429.         ID
  2430.         << this_var = new_var_id(&$1);
  2431.            if (this_var != NULL) append_pvec($v_list, (void *)this_var);
  2432.         >>
  2433.         (
  2434.         COMMA ID
  2435.         << this_var = new_var_id(&$2);
  2436.            if (this_var != NULL) append_pvec($v_list, (void *)this_var);
  2437.         >>
  2438.         )*
  2439.         ;
  2440.  
  2441. The "pvec" stuff above is just a vector of pointers that can be
  2442. extended automatically. A linked list would work just as well.  The
  2443. idea is that we must first collect the declared variables, then
  2444. parse the type declaration, then apply bind the type to the declared
  2445. variables.  We used ANTLR's auto-tree-generation mode, and didn't
  2446. override its actions with our own.  Therefore, the following Sorcerer
  2447. fragment will recognize the AST  built for a variable declaration:
  2448.                                                                      Page 51
  2449.  
  2450. var_declare:
  2451.         #( VAR
  2452.           ( v_list: var_id_list COLON
  2453.             { EXTERN | STATIC }
  2454.             type
  2455.             { ASSIGNMENT expr }
  2456.             SEMI
  2457.           )+
  2458.         )
  2459.         ;
  2460. var_id_list:
  2461.         ID ( COMMA ID)*
  2462.         ;
  2463.  
  2464. Here's an example, where we use explicit rules to build an AST:
  2465.  
  2466. expr!:
  2467.         simple_expr
  2468.         << $expr = $1; #0 = #1; >>
  2469.         ( rel_op simple_expr
  2470.           << parse_binary_op(&$expr, &$1, &$2); #0 = #(NULL, #0, #1, #2); >>
  2471.         )*
  2472.         << $expr.token = EXPR;
  2473.            $expr.text = "expr";
  2474.            #0 = #(#[&$expr], #0);
  2475.         >>
  2476.         ;
  2477.  
  2478. The construct, #[&$expr] first takes the address of the $expr
  2479. attribute (attributes are structures, not pointers, in this example),
  2480. and then applies the #[] operation which makes a call to the routine
  2481. that creates an AST node, given an attribute (or attribute address
  2482. in our case).  It takes a while to get the hang of where the &'s
  2483. #'s, and $'s go, but can be a real time-saver once you master it.
  2484. What we're doing above is building a special EXPR (expression) node.
  2485. This node would be parsed as follows in subsequent passes, using
  2486. Sorcerer:
  2487.  
  2488. expr:   #( e: EXPR
  2489.            l_oprnd: simple_expr  << e->typ = l_oprnd->typ; >>
  2490.              (op: rel_op  r_oprnd: simple_expr
  2491.                   <<
  2492.                       e->typ = std_bool_type->obj_type;
  2493.                       if (op->token == IN) {
  2494.                           /* no type conversion checking for IN.
  2495.                            * try to rewrite simple IN ops.
  2496.                            */
  2497.                           if (is_simple_in_op(l_oprnd, op, r_oprnd)) {
  2498.                               rewrite_simple_in_op(l_oprnd, op, r_oprnd);
  2499.                           }
  2500.                       } else {
  2501.                           cvt_term(&l_oprnd, op, r_oprnd, _t);
  2502.                       }
  2503.                   >>
  2504.              )*
  2505.         );
  2506.                                                                      Page 52
  2507.  
  2508. We left in the actual actions of the second (Sorcerer driven) pass.
  2509. Notice how the Sorcerer grammar labels various parts of the expr
  2510. node ('e', 'l_oprnd', 'op', and 'r_oprnd').  This gives the second
  2511. pass access to each node, as it is recognized.
  2512.  
  2513. The second pass uses the 'typ' field, which contains the type of
  2514. the ID, expression, or literal parsed by the first pass.  In the
  2515. actions above, we are propagating additional type information (for
  2516. example, the result of a relational op is always a boolean, checking
  2517. for implicit type conversions, and handling simple cases of Pascal's
  2518. IN operation).  The fragment above is from a Pascal to Ada translator,
  2519. so the translator has to make Pascal's implicit type conversions
  2520. between integer and real into explicit Ada type conversions, and
  2521. has to convert operations on sets (i.e. IN) into operations on
  2522. packed boolean arrays, in Ada, or calls to runtime routines.
  2523.  
  2524. Sometimes when you are building the AST for a given construct,
  2525. you need to use information gained from semantic analysis.  An
  2526. example is the "assignment" or "call" statement:
  2527.  
  2528. /*
  2529.  * If a variable access appears alone, then it must be either a call to
  2530.  * procedure with no parameters, or an indirection through a pointer
  2531.  * to a procedure with no parameters.
  2532.  */
  2533. assign_or_call_stmt!:
  2534.         << type_ref r_type = NULL;
  2535.            ast_ref v;
  2536.         >>
  2537.         variable
  2538.           << v = #1;
  2539.              $assign_or_call_stmt       = $1;
  2540.              $assign_or_call_stmt.token = PROC_CALL;
  2541.              $assign_or_call_stmt.text  = "proc_call";
  2542.              r_type = $assign_or_call_stmt.typ;
  2543.              if (v != NULL && v->obj != NULL
  2544.                  && v->obj->obj_result != NULL
  2545.                  && v->obj->obj_kind == func_obj
  2546.                  && v->down->token == ID
  2547.                  && v->down->right == NULL) {
  2548.                    object_ref func = v->obj;
  2549.                    /* function name used on left hand side;
  2550.                     * convert to reference to the function's return value
  2551.                     */
  2552.                    v->obj  = func->obj_result;
  2553.                    v->typ  = func->obj_result->obj_type;
  2554.                    v->down->text = func->obj_result->obj_name;
  2555.                    v->down->obj  = func->obj_result;
  2556.                    v->down->typ  = func->obj_result->obj_type;
  2557.              }
  2558.              #0 = v;
  2559.           >>
  2560.                                                                      Page 53
  2561.  
  2562.         { ASSIGNMENT expr
  2563.           << $assign_or_call_stmt.token = ASSIGNMENT;
  2564.              $assign_or_call_stmt.text  = ":=";
  2565.              mark_var_use(#2, VAR_RHS);
  2566.              mark_var_use(v, VAR_LHS);
  2567.              #0 = #(NULL, #0, #[&$1], #2);
  2568.           >>
  2569.           | ( LPAREN actual_param_list RPAREN
  2570.               << mark_actual_param_use(#2, r_type);
  2571.                  mark_var_use(v, VAR_RHS);
  2572.                  #0 = #(NULL, #0, #[&$1], #2, #[&$3]);
  2573.               >>
  2574.             )
  2575.         }
  2576.         << #0 = #( #[&$assign_or_call_stmt], #0); >>
  2577.         ;
  2578.  
  2579.  
  2580. The problem we're solving is that both an assignment statement and
  2581. a procedure call statement begin with a "variable".  Since ANTLR
  2582. is LL-based, this statement construct is "ambiguous" in that
  2583. both statement types (assignment and call) begin with the same
  2584. non-terminal.  A "variable" includes operations such operations
  2585. as array subscripting, pointer deferencing, and record field selection.
  2586. Thus, a "variable" may comprise an arbitrary number of tokens.
  2587.  
  2588. We might use syntactic predicates as a form a look-ahead to resolve
  2589. the two cases above, but instead I decided to make the assumption that
  2590. we have "PROC_CALL", and to correct that "guess" once we see the
  2591. assignment operation.  Thus, the above rule will build one of the
  2592. following two AST structures:
  2593.  
  2594. assign_stmt:
  2595.         #( ASSIGNMENT
  2596.         variable  ASSIGNMENT expr
  2597.         )
  2598.         ;
  2599. call_stmt:
  2600.         #( PROC_CALL
  2601.         variable {LPAREN actual_param_list RPAREN}
  2602.         )
  2603.         ;
  2604.  
  2605. In your AST, you might want to drop unnecessary syntactic tokens such as
  2606. ASSIGNMENT, LPAREN, RPAREN, COMMA, COLON, etc. We kept them, because we
  2607. thought it would be necessary for certain parts of source-to-source
  2608. translation.  We don't think that's true, any more, but have not gone back
  2609. and changed the AST structure either.
  2610.                                                                      Page 54
  2611.  
  2612. 3) Build a separate Sorcerer grammar file to recognize the AST that you
  2613. have built, and then add your second pass actions.  These actions will
  2614. access fields in the AST node, that were filled in by the first pass.  For
  2615. example, identifiers will probably have an "object_ref" that points to the
  2616. object named by the identifier, and expression (EXPR) nodes will have a
  2617. "typ" field that gives the expression's type. You might also add a "value"
  2618. field that gives the value of a literal, named literal, or statically
  2619. evaluated constant expression. See the code fragments above for some ideas
  2620. on how this is done.
  2621.  
  2622. Conclusions:
  2623.  
  2624.    1) You'll need an ANTLR (.g) description for pass1, and a separate
  2625.    Sorcerer (.sor) description for pass2.  Often the pass2 AST
  2626.    representation is much more regular and well-formed than the
  2627.    original text token stream used by pass1.
  2628.  
  2629.    2) It can be a bit intimidating putting the pieces together.
  2630.    Try it incrementally, trying a small subset of your larger
  2631.    problem.
  2632.  
  2633.    3) There are a lot of ways to go with how you represent
  2634.    attributes ($-variables), AST nodes, and the things that
  2635.    go on in various passes.  For example, you might have
  2636.    pass1 simply build the AST and perform *no* symbol definitions
  2637.    or semantic checks.  Then pass2 might walk the tree and build
  2638.    the symbol, and make various checks. Pass2 might also disambiguate
  2639.    cases that look syntactically similar, and can only be disambiguated
  2640.    using symbol definitions.  Then, you could have a pass3 (another
  2641.    Sorcerer driven tree-walk) that does the 'real work' of your
  2642.    compiler/translator.
  2643.  
  2644. Contributed by Gary Funck (gary@intrepid.com)
  2645.                                                                      Page 55
  2646.  
  2647. ===============================================================================
  2648. Example 1 of #lexclass
  2649. ===============================================================================
  2650. Borrowed code
  2651. -------------------------------------------------------------------------------
  2652. /*
  2653.  * Various tokens
  2654.  */
  2655. #token "[\t\ ]+"        << zzskip(); >> /* Ignore whitespace */
  2656. #token "\n"             << zzline++; zzskip(); >> /* Count lines */
  2657.  
  2658. #token "\""             << zzmode(STRINGS); zzmore(); >>
  2659. #token "'"              << zzmode(CHARACTERS); zzmore(); >>
  2660. #token "/\*"            << zzmode(COMMENT); zzskip(); >>
  2661. #token "//"             << zzmode(CPPCOMMENT); zzskip(); >>
  2662.  
  2663. /*
  2664.  * C++ String literal handling
  2665.  */
  2666. #lexclass STRINGS
  2667. #token STRING "\""      << zzmode(START); >>
  2668. #token "\\\""           << zzmore(); >>
  2669. #token "\\n"            << zzreplchar('\n'); zzmore(); >>
  2670. #token "\\r"            << zzreplchar('\r'); zzmore(); >>
  2671. #token "\\t"            << zzreplchar('\t'); zzmore(); >>
  2672. #token "\\[1-9][0-9]*"  << zzreplchar((char)strtol(zzbegexpr, NULL, 10));
  2673.                            zzmore(); >>
  2674. #token "\\0[0-7]*"      << zzreplchar((char)strtol(zzbegexpr, NULL, 8));
  2675.                            zzmore(); >>
  2676. #token "\\0x[0-9a-fA-F]*" << zzreplchar((char)strtol(zzbegexpr, NULL, 16));
  2677.                              zzmore(); >>
  2678. #token "\\~[\n\r]"      << zzmore(); >>
  2679. #token "[\n\r]"         << zzline++; zzmore(); /* Print warning */ >>
  2680. #token "~[\"\n\r\\]+"   << zzmore(); >>
  2681.  
  2682. /*
  2683.  * C++ Character literal handling
  2684.  */
  2685. #lexclass CHARACTERS
  2686. #token CHARACTER "'"    << zzmode(START); >>
  2687. #token "\\'"            << zzmore(); >>
  2688. #token "\\n"            << zzreplchar('\n'); zzmore(); >>
  2689. #token "\\r"            << zzreplchar('\r'); zzmore(); >>
  2690. #token "\\t"            << zzreplchar('\t'); zzmore(); >>
  2691. #token "\\[1-9][0-9]*"  << zzreplchar((char)strtol(zzbegexpr, NULL, 10));
  2692.                            zzmore(); >>
  2693. #token "\\0[0-7]*"      << zzreplchar((char)strtol(zzbegexpr, NULL, 8));
  2694.                            zzmore(); >>
  2695. #token "\\0x[0-9a-fA-F]*" << zzreplchar((char)strtol(zzbegexpr, NULL, 16));
  2696.                              zzmore(); >>
  2697. #token "\\~[\n\r]"      << zzmore(); >>
  2698. #token "[\n\r]"         << zzline++; zzmore(); /* Print warning */ >>
  2699. #token "~[\'\n\r\\]"    << zzmore(); >>
  2700.                                                                      Page 56
  2701.  
  2702. /*
  2703.  * C-style comment handling
  2704.  */
  2705. #lexclass COMMENT
  2706. #token "\*/"            << zzmode(START); zzskip(); >>
  2707. #token "~[\*]*"         << zzskip(); >>
  2708. #token "\*~[/]"         << zzskip(); >>
  2709.  
  2710. /*
  2711.  * C++-style comment handling
  2712.  */
  2713. #lexclass CPPCOMMENT
  2714. #token "[\n\r]"         << zzmode(START); zzskip(); >>
  2715. #token "~[\n\r]"        << zzskip(); >>
  2716.  
  2717. #lexclass START
  2718.  
  2719. /*
  2720.  * Assorted literals
  2721.  */
  2722. #token OCT_NUM "0[0-7]*"
  2723. #token L_OCT_NUM "0[0-7]*[Ll]"
  2724. #token INT_NUM "[1-9][0-9]*"
  2725. #token L_INT_NUM "[1-9][0-9]*[Ll]"
  2726. #token HEX_NUM "0[Xx][0-9A-Fa-f]+"
  2727. #token L_HEX_NUM "0[Xx][0-9A-Fa-f]+[Ll]"
  2728. #token FLOAT_NUM "([1-9][0-9]*{.[0-9]*} | {0}.[0-9]+) {[Ee]{[\+\-]}[0-9]+}"
  2729.  
  2730. /*
  2731.  * Identifiers
  2732.  */
  2733. #token Identifier "[_a-zA-Z][_a-zA-Z0-9]*"
  2734.                                                                      Page 57
  2735.  
  2736. ===============================================================================
  2737. Example 2: ASTs
  2738. ===============================================================================
  2739. #header <<
  2740.  
  2741. #include "charbuf.h"
  2742. #include <string.h>
  2743.  
  2744. int nextSerial;
  2745.  
  2746. #define AST_FIELDS int token; int serial; char *text;
  2747. #include "ast.h"
  2748.  
  2749. #define zzcr_ast(ast,attr,tok,astText) \
  2750.    (ast)->token=tok; \
  2751.    (ast)->text=strdup( (char *)  &(  (  (attr)->text  )  )  ); \
  2752.    nextSerial++; \
  2753.    (ast)->serial=nextSerial; \
  2754.  
  2755. #define zzd_ast(node) delete_ast(node)
  2756.  
  2757. void delete_ast (AST *node);
  2758.  
  2759. >>
  2760.  
  2761. <<
  2762.  
  2763. AST     *root=NULL;
  2764.  
  2765. void show(AST *tree) {
  2766.         if (tree->token==ID) {
  2767.           printf (" %s <#%d> ",
  2768.                 tree->text,tree->serial);}
  2769.         else {
  2770.           printf (" %s <#%d> ",
  2771.                 zztokens[tree->token],
  2772.                 tree->serial);
  2773.         };
  2774. }
  2775. void before (AST *tree) {
  2776.         printf ("(");
  2777. }
  2778. void after (AST *tree) {
  2779.         printf (")");
  2780. }
  2781.  
  2782.  
  2783. void delete_ast(AST *node) {
  2784.   printf ("\nzzd_ast called for <node #%d>\n",node->serial);
  2785.   free (node->text);
  2786.   return;
  2787. }
  2788.  
  2789. int main() {
  2790.         nextSerial=0;
  2791.         ANTLR (expr(&root),stdin);
  2792.         printf ("\n");
  2793.         zzpre_ast(root,show,before,after);
  2794.         printf ("\n");
  2795.         zzfree_ast(root);
  2796.         return 0;
  2797. }
  2798. >>
  2799.                                                                      Page 59
  2800.  
  2801. #token  WhiteSpace      "[\ \t]"                <<zzskip();>>
  2802. #token  ID              "[a-z A-Z]*"
  2803. #token  NEWLINE         "\n"
  2804. #token  OpenAngle       "<"
  2805. #token  CloseAngle      ">"
  2806.  
  2807. expr    : (expr0 NEWLINE)
  2808.  
  2809. ;expr0  : expr1 {"="^ expr0}
  2810. ;expr1  : expr2 ("\+"^ expr2)*
  2811. ;expr2  : expr3 ("\*"^ expr3)*
  2812. ;expr3  : ID
  2813. -------------------------------------------------------------------------------
  2814. Sample output from this program:
  2815.  
  2816. a=b=c=d
  2817. ( = <#2>  a <#1> ( = <#4>  b <#3> ( = <#6>  c <#5>  d <#7> ))) NEWLINE <#8>
  2818. zzd_ast called for <node #7>
  2819. zzd_ast called for <node #5>
  2820. zzd_ast called for <node #6>
  2821. zzd_ast called for <node #3>
  2822. zzd_ast called for <node #4>
  2823. zzd_ast called for <node #1>
  2824. zzd_ast called for <node #8>
  2825. zzd_ast called for <node #2>
  2826.  
  2827. a+b*c
  2828. ( \+ <#2>  a <#1> ( \* <#4>  b <#3>  c <#5> )) NEWLINE <#6>
  2829. zzd_ast called for <node #5>
  2830. zzd_ast called for <node #3>
  2831. zzd_ast called for <node #4>
  2832. zzd_ast called for <node #1>
  2833. zzd_ast called for <node #6>
  2834. zzd_ast called for <node #2>
  2835.  
  2836. a*b+c
  2837. ( \+ <#4> ( \* <#2>  a <#1>  b <#3> ) c <#5> ) NEWLINE <#6>
  2838. zzd_ast called for <node #3>
  2839. zzd_ast called for <node #1>
  2840. zzd_ast called for <node #5>
  2841. zzd_ast called for <node #2>
  2842. zzd_ast called for <node #6>
  2843. zzd_ast called for <node #4>
  2844.                                                                      Page 61
  2845.  
  2846. ===============================================================================
  2847. Example 3: Syntactic Predicates
  2848. ===============================================================================
  2849. Not completed.
  2850. ===============================================================================
  2851. Example 4: DLG input function
  2852. ===============================================================================
  2853. This example demonstrates the use of a DLG input function to work
  2854. around a limitation of DLG.  In this example the user wants to
  2855. recognize an exclamation mark as the first character of a line and
  2856. treat it differently from an exclamation mark elsewhere.  The
  2857. workaround is for the input function to return a non-printing
  2858. character (binary 1) when it finds an "!" in column 1.  If it reads a
  2859. genuine binary 1 in column 1 of the input text it returns a "?".
  2860.  
  2861. The parse is started by:
  2862.  
  2863.         int DLGchar (void);
  2864.         ...
  2865.         ANTLRf (expr(&root),DLGchar);
  2866.         ...
  2867. -------------------------------------------------------------------------------
  2868. #token  BANG            "!"
  2869. #token  BANG_COL1       "\01"
  2870. #token  WhiteSpace      "[\ \t]"        <<zzskip();>>
  2871. #token  ID              "[a-z A-Z]*"
  2872. #token  NEWLINE         "\n"
  2873.  
  2874. expr!   : (bang         <<printf ("\nThe ! is NOT in column 1\n");>>
  2875.            | bang1      <<printf ("\nThe ! is in column 1\n");>>
  2876.            | id         <<printf ("\nFirst token is an ID\n");>>
  2877.           )* "@"
  2878.  
  2879. ;bang!  : BANG ID NEWLINE
  2880.  
  2881. ;bang1! : BANG_COL1 ID  NEWLINE
  2882.  
  2883. ;id!    : ID  NEWLINE
  2884. ;
  2885. -------------------------------------------------------------------------------
  2886.                                                                      Page 62
  2887.  
  2888. #include <stdio.h>
  2889.  
  2890. /*
  2891.         Antlr DLG input function - See page 18 of pccts 1.00 manual
  2892. */
  2893.  
  2894. static int firstTime=1;
  2895.  
  2896. static int c;
  2897.  
  2898. int DLGchar (void) {
  2899.     if (feof(stdin)) {
  2900.         return EOF;
  2901.     };
  2902.     if (firstTime || c=='\n') {
  2903.       firstTime=0;
  2904.       c=fgetc(stdin);
  2905.       if (c==EOF) return (EOF);
  2906.       if (c=='!') return ('\001');
  2907.       if (c=='\001') return ('?');
  2908.       return (c);
  2909.     } else {
  2910.       c=fgetc(stdin);
  2911.       return (c);
  2912.     };
  2913. };
  2914.                                                                      Page 63
  2915.  
  2916. ===============================================================================
  2917. Example 5: Maintaining a Stack of DLG Modes
  2918. ===============================================================================
  2919. Contributed by David Seidel
  2920. Normally this should be appended to err.h
  2921. -------------------------------------------------------------------------------
  2922. #define  MAX_MODE ????
  2923. #define  ZZMAXSTK (MAX_MODE * 2)
  2924.  
  2925. static int  zzmstk[ZZMAXSTK] = { -1 };
  2926. static int  zzmdep = 0;
  2927.  
  2928. void
  2929. #ifdef __STDC__
  2930. zzmpush( int m )
  2931. #else
  2932. zzmpush( m )
  2933. int m;
  2934. #endif
  2935. {
  2936.    if(zzmdep == ZZMAXSTK - 1)
  2937.    {  sprintf(zzebuf, "Mode stack overflow ");
  2938.       zzerr(zzebuf);
  2939.    }
  2940.    else
  2941.    {  zzmstk[zzmdep++] = zzauto;
  2942.       zzmode(m);
  2943.    }
  2944. }
  2945.  
  2946. void
  2947. zzmpop()
  2948. {
  2949.    if(zzmdep == 0)
  2950.    {  sprintf(zzebuf, "Mode stack underflow ");
  2951.       zzerr(zzebuf);
  2952.    }
  2953.    else
  2954.    {  zzmdep--;
  2955.       zzmode(zzmstk[zzmdep]);
  2956.    }
  2957. }
  2958.                                                                      Page 64
  2959.  
  2960. -------------------------------------------------------------------------------
  2961. A modified version of the above routine which allows the user to pass a
  2962. "lookahead" routine to be called when the mode stack is popped.  Normally
  2963. this will be appended to err.h.
  2964. -------------------------------------------------------------------------------
  2965. #define ZZMAXSTK ????
  2966.  
  2967. static int  zzmstk[ZZMAXSTK] = { -1 };  /* stack of DLG modes */
  2968. static void (*zzfuncstk[ZZMAXSTK])();   /* stack of pointer to functions */
  2969. static int  zzmdep = 0;
  2970.  
  2971. void pushMode( int m ,void (*func)())
  2972. {
  2973.    if(zzmdep == ZZMAXSTK - 1)
  2974.    {  sprintf(message, "Mode stack overflow ");
  2975.       zzerr(message);
  2976.    }
  2977.    else
  2978.    {  zzmstk[zzmdep] = zzauto;
  2979.       zzfuncstk[zzmdep] = func;
  2980.       zzmdep++;
  2981.       zzmode(m);
  2982.    }
  2983. }
  2984.  
  2985. void popMode()
  2986. {
  2987.    void (*thisFunc)();
  2988.    if(zzmdep == 0)
  2989.    {  sprintf(message, "Mode stack underflow ");
  2990.       zzerr(message);
  2991.    }
  2992.    else
  2993.    {  zzmdep--;
  2994.       thisFunc=zzfuncstk[zzmdep];
  2995.       zzmode(zzmstk[zzmdep]);
  2996.       zzmstk[zzmdep]=0;
  2997.       zzfuncstk[zzmdep]=0;
  2998.         /* this call might result in indirect recursion of popMode() */
  2999.       if (thisFunc!=0) {
  3000.         (*thisFunc)();
  3001.       };
  3002.    }
  3003. }
  3004.  
  3005. void resetModeStack() {
  3006.    zzmdep=0;
  3007.    zzmstk[0]=0;
  3008.    zzfuncstk[0]=0;
  3009. }
  3010.  
  3011. /*  if the lookahead character is a semi-colon then keep on popping */
  3012.  
  3013. void popOnSC() {
  3014.    if (zzchar==';') popMode();
  3015. }
  3016.                                                                      Page 65
  3017.  
  3018. ===============================================================================
  3019. Example 6: Debug code for create_ast, mk_ast, delete_ast to locate lost ASTs
  3020. ===============================================================================
  3021. This is an example of code which tries to keep track of lost ASTs using
  3022. a doubly linked list of all ASTs maintained by calls from create_ast()
  3023. and mk_ast() to zzastnew_userhook().  When ASTs are deleted by calls
  3024. to zzastdelete_userhook() from the user's AST delete routines they are
  3025. removed from the doubly linked list.  Any ASTs left over after zzfree_ast()
  3026. must be considered lost.
  3027.  
  3028. This method does not monitor ASTs created by zzdup_ast() because it does
  3029. not call the create_ast() or mk_ast() routines.
  3030. -------------------------------------------------------------------------------
  3031. The #header section must include a definition of AST_FIELDS with the
  3032. equivalent of:
  3033.  
  3034.         struct _ast *flink, *blink;
  3035. -------------------------------------------------------------------------------
  3036. int main() {
  3037.     ...
  3038. again:
  3039.     ...
  3040.     reset_ASTlistHead();        /*  <======================== */
  3041.     ANTLR (sourcecode(&root),stdin);
  3042.     treewalk(root);
  3043.     zzfree_ast(root);
  3044.     root=NULL;
  3045.     print_lost_ast();           /*   <======================= */
  3046.     printf ("\n");}
  3047.     ...
  3048.     goto again;
  3049.     ...
  3050. }
  3051. -------------------------------------------------------------------------------
  3052. #ifndef H_ZZNEWAST_USERHOOK
  3053. #define H_ZZNEWAST_USERHOOK
  3054.  
  3055. void reset_ASTlistHead(void);
  3056. void zzunhook_tree(void);
  3057. void zzastnew_userhook(AST *newNode);
  3058. void zzastdelete_userhook (AST *singleNode);
  3059. void print_lost_ast (void);
  3060. void treewalk(AST *tree);
  3061.  
  3062. #endif
  3063. -------------------------------------------------------------------------------
  3064. #include "stdpccts.h"
  3065. #include "stdlib.h"
  3066. #include "zzastnew_userhook.h"
  3067.  
  3068. static AST ASTlistHead;
  3069. static int ASTserialNumber;
  3070.  
  3071. void reset_ASTlistHead(void) {
  3072.   while (ASTlistHead.flink!=0 && ASTlistHead.flink!= &ASTlistHead) {
  3073.          zzfree_ast(ASTlistHead.flink);
  3074.   };
  3075.   ASTlistHead.flink=&ASTlistHead;
  3076.   ASTlistHead.blink=&ASTlistHead;
  3077.   ASTserialNumber=1;
  3078.   return;
  3079. }
  3080.                                                                      Page 66
  3081.  
  3082. /*  Stop tracking ASTs in a tree without actually deleting them */
  3083.  
  3084. void zzunhook_tree (AST * tree) {
  3085.  
  3086.         while (tree != 0) {
  3087.           zzunhook_tree (tree->down);
  3088.           zzastdelete_userhook (tree);
  3089.           tree=tree->right;
  3090.         };
  3091.         return;
  3092. }
  3093.  
  3094. /*  Track new AST */
  3095.  
  3096. void zzastnew_userhook(AST *newNode) {
  3097.  
  3098.         AST  *prev;
  3099.  
  3100.         prev=ASTlistHead.blink;
  3101.         prev->flink=newNode;
  3102.         ASTlistHead.blink=newNode;
  3103.         newNode->blink=prev;
  3104.         newNode->flink=&ASTlistHead;
  3105.         newNode->serialNumber=ASTserialNumber;
  3106.         ASTserialNumber++;
  3107.         return;
  3108. }
  3109.  
  3110. /*  Stop tracking an AST */
  3111.  
  3112. void zzastdelete_userhook (AST *singleNode) {
  3113.  
  3114.         AST *fnode;
  3115.         AST *bnode;
  3116.  
  3117.         if (singleNode!=0) {
  3118.                 fnode=singleNode->flink;
  3119.                 bnode=singleNode->blink;
  3120.                 fnode->blink=bnode;
  3121.                 bnode->flink=fnode;
  3122.                 singleNode->serialNumber=0;
  3123.                 singleNode->flink=0;
  3124.                 singleNode->blink=0;
  3125.         };
  3126.         return;
  3127. }
  3128.  
  3129. /*  Print ASTs that are still on list */
  3130.  
  3131. void print_lost_ast () {
  3132.  
  3133.   AST *node;
  3134.  
  3135.   for (node=ASTlistHead.flink;
  3136.        node!=0 && node!= &ASTlistHead;
  3137.        node=node->flink) {
  3138.          printf ("**** Start of lost AST listing **** %d\n",node->serialNumber);
  3139.          treewalk (node);               /*  user supplied routine */
  3140.          printf ("\n**** End of lost AST listing ****\n");
  3141.        };
  3142. }
  3143.                                                                      Page 68
  3144.  
  3145. -------------------------------------------------------------------------------
  3146. These routines print out the AST tree.  This will be application dependent.
  3147. -------------------------------------------------------------------------------
  3148. #include "stdpccts.h"
  3149. #include "stdlib.h"
  3150.  
  3151. static int treenest=0;
  3152.  
  3153. void  treeindent(int nesting) {
  3154.   int i;
  3155.   for (i=0;i<nesting*2;i++) {
  3156.     printf (" ");
  3157.   };
  3158.   return;
  3159. }
  3160.  
  3161. void treewalk1 (AST *tree) {
  3162.         while (tree != NULL) {
  3163.                 treeindent(treenest);
  3164.                 printf ("%s",zztokens[tree->token]);
  3165.                 if (tree->text != NULL) {
  3166.                   printf ("  %s",tree->text);
  3167.                 };
  3168.                 printf ("\n");
  3169.                 treenest++;
  3170.                 treewalk1 (tree->down);
  3171.                 treenest--;
  3172.                 tree=tree->right;
  3173.         };
  3174.         return;
  3175. }
  3176.  
  3177. void treewalk (AST *tree) {
  3178.   treenest=0;
  3179.   treewalk1(tree);
  3180.   return;
  3181. }
  3182. -------------------------------------------------------------------------------
  3183.